Bash script / awk do wprowadzenia i wyprowadzenia pliku CSV
Mam problem z utworzeniem skryptu bash / awk / sed, który pobierałby plik CSV oddzielony przecinkami składający się z trzech kolumn (imię, nazwisko, data urodzenia) i wyświetlał inny plik CSV, który ma te same kolumny z danych wejściowych dodatkowa kolumna pokazująca różnicę między aktualną datą a datą urodzenia w latach.
$ yourscript <input CSV file> <output CSV file>
input.csv może wyglądać tak:
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
output.csv powinien wyglądać następująco:
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48
Odpowiedzi
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Aby wyprowadzić w pliku o nazwie output-filei jednocześnie wyświetlić na 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
Lub po prostu wyślij do tego samego pliku:
$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data > output-file
Aby wykonać dokładniejsze obliczenia czasu, można użyć gawk„s funkcje czasowe i ciągów (za sugestią AdminBee za @). Korzystanie z danych wejściowych jako:
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Możesz uzyskać różnicę czasu w dniach między teraz a datą wyświetlaną w każdym wierszu, stosując:
$ 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
Fragment:
int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))
wykonuje trzy podstawowe rzeczy dla każdej linii pliku wejściowego:
- oblicza czas, który upłynął (w sekundach) od 1970-01-01 00:00:00 UTC (w systemach POSIX), nie licząc sekund przestępnych, z
mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00) - oblicza różnicę czasu między powyższą wielkością a zmienną
today, która zawiera liczbę sekund, które upłynęły od czasu wykonania od 1970-01-01 00:00:00 UTC. - dzieli różnicę czasu w sekundach przez 3600 * 24, aby uzyskać to samo w dniach, i bierze pod uwagę tylko całkowitą część wyniku, aby otrzymać całe dni
int().
Możesz się tym bawić, aby uzyskać różnicę czasu w sekundach, minutach, godzinach w zależności od potrzeb. HTH
Aby uzyskać różnicę w datach, możesz użyć tej małej funkcji bash
Użyj następujących numerów do swoich potrzeb
- # Aby uzyskać różnicę dni : 86400
- # Aby uzyskać różnicę lat : 31536000
Funkcja Bash
datediff() {
current_date=$(date -d "$1" +%s)
birth_date=$(date -d "$2" +%s)
echo $(( (current_date - birth_date) / 31536000)) Years
}
Stosowanie:
datediff '9/28/2020' '1/1/1999'
Wynik:
21 years
W zależności od tego, czego naprawdę chcesz:
różnica lat:
(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
wiek:
(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 i csv-header pochodzą z csv-nix-tools