Bash script / awk per inserire e produrre un file CSV
Ho qualche problema a creare uno script bash / awk / sed che richiederebbe un file CSV separato da virgole di tre colonne (nome, cognome, data di nascita) e restituisce un altro file CSV con le stesse colonne dall'input con un colonna aggiuntiva che mostra la differenza tra la data corrente e la data di nascita in anni.
$ yourscript <input CSV file> <output CSV file>
input.csv potrebbe essere simile a questo:
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
output.csv dovrebbe essere simile a questo:
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48
Risposte
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Per output-fileeseguire l' output in un file denominato e visualizzare contemporaneamente in STDOUT:
$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data | tee output-file
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48
O solo per eseguire l'output nello stesso file:
$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data > output-file
Per eseguire calcoli di tempo più accurati, è possibile utilizzare gawkle funzioni di tempo e stringa di (secondo il suggerimento di @ AdminBee). Utilizzo dei dati di input come:
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Puoi ottenere una differenza di orario in giorni tra adesso e la data mostrata su ogni riga, con:
$ awk -F, 'BEGIN{today=systime()}
{print $0 "," int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))}' \
data | tee output-file
bob,wag,06/13/1958,22755
ashley,hay,01/23/1983,13765
evan,bert,09/11/1972,17551
Lo snippet:
int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))
fa tre cose fondamentali per ogni riga del file di input:
- calcola il tempo trascorso (in secondi) dal 1970-01-01 00:00:00 UTC (su sistemi POSIX), senza contare i secondi intercalari, con
mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00) - calcola la differenza di tempo tra la quantità di cui sopra e la variabile
today, che contiene il numero di secondi trascorsi al momento dell'esecuzione dal 1970-01-01 00:00:00 UTC. - divide la differenza di tempo in secondi per 3600 * 24 per ottenere lo stesso in giorni e considera solo la parte intera del risultato, per ottenere giorni interi
int().
Puoi giocarci per ottenere la tua differenza di orario in secondi, minuti, ore secondo le tue necessità. HTH
Per ottenere la differenza di data, puoi usare questa piccola funzione bash
Usa i seguenti numeri per le tue esigenze
- #Per ottenere la differenza di giorni : 86400
- #Per ottenere la differenza di anni : 31536000
Funzione Bash
datediff() {
current_date=$(date -d "$1" +%s)
birth_date=$(date -d "$2" +%s)
echo $(( (current_date - birth_date) / 31536000)) Years
}
Utilizzo:
datediff '9/28/2020' '1/1/1999'
Produzione:
21 years
A seconda di cosa vuoi veramente:
differenza di anni:
(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite \
"select *, strftime('%Y', 'now') - substr(d, 7, 4) as year_diff
from input" | csv-header --remove
età:
(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite
"select *, strftime('%Y', 'now') - substr(d, 7, 4) -
case when strftime('%m%d', 'now') >= (substr(d, 1, 2) || substr(d, 4, 2))
then 0 else 1 end as age
from input" | csv-header --remove
csv-sqlite e csv-header provengono da csv-nix-tools