Script Bash / awk pour entrer et sortir un fichier CSV
J'ai du mal à créer un script bash / awk / sed qui prendrait un fichier CSV séparé par des virgules de trois colonnes (prénom, nom, date de naissance) et produirait un autre fichier CSV qui a les mêmes colonnes d'entrée avec un colonne supplémentaire qui montre la différence entre la date actuelle et la date de naissance en années.
$ yourscript <input CSV file> <output CSV file>
input.csv peut ressembler à ceci:
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
output.csv devrait ressembler à ceci:
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48
Réponses
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Pour sortir dans un fichier nommé output-fileet afficher dans STDOUT en même temps:
$ 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
Ou pour simplement sortir dans le même fichier:
$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data > output-file
Pour effectuer des calculs de temps plus précis, vous pouvez utiliser gawkles fonctions de temps et de chaîne (selon la suggestion de @ AdminBee). Utilisation des données d'entrée comme:
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Vous pouvez obtenir un décalage horaire en jours entre maintenant et la date indiquée sur chaque ligne, avec:
$ 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
L'extrait:
int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))
fait trois choses de base pour chaque ligne du fichier d'entrée:
- il calcule le temps écoulé (en secondes) depuis 1970-01-01 00:00:00 UTC (sur les systèmes POSIX), sans compter les secondes intercalaires, avec
mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00) - il calcule la différence de temps entre la quantité ci-dessus et la variable
today, qui contient le nombre de secondes écoulées au moment de l'exécution depuis 1970-01-01 00:00:00 UTC. - il divise la différence de temps en secondes par 3600 * 24 pour obtenir la même valeur en jours, et ne considère que la partie entière du résultat, pour obtenir des jours entiers
int().
Vous pouvez jouer avec cela pour obtenir votre décalage horaire en secondes, minutes, heures selon vos besoins. HTH
Pour obtenir la différence de date, vous pouvez utiliser cette petite fonction bash
Utilisez les numéros suivants pour vos besoins
- #Pour obtenir la différence de jours : 86400
- #Pour obtenir la différence d' années : 31536000
Fonction Bash
datediff() {
current_date=$(date -d "$1" +%s)
birth_date=$(date -d "$2" +%s)
echo $(( (current_date - birth_date) / 31536000)) Years
}
Usage:
datediff '9/28/2020' '1/1/1999'
Production:
21 years
Selon ce que vous voulez vraiment:
différence d'années:
(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
âge:
(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 et csv-header sont issus de csv-nix-tools