1
votes

Utilisez awk pour analyser le fichier csv - combiné avec la commande shell 'date' dans awk

J'ai un fichier .csv qui a des dates et la réponse à propos agréable ou non:

dates=$(awk '{FS=","}{print $1,$2}' weather_stat.csv')

weeks=$(
for vars in $dates[first_row]
do
echo $(date -j -f '%Y-%m-%d' $vars "+%w")
done
)

merge($dates,$weeks)

Ce que je veux faire est d'imprimer le jour de la semaine dans la troisième colonne séparé par ',' comme ceci:

2019-04-1,enjoyable,2
2019-04-2,unenjoyable,3

J'ai essayé:

2019-04-1,enjoyable
2019-04-2,unenjoyable
2019-04-3,unenjoyable
2019-04-4,enjoyable
2019-04-5,unenjoyable
2019-04-6,unenjoyable
2019-04-7,enjoyable
2019-04-8,unenjoyable
2019-04-9,unenjoyable
2019-04-10,enjoyable
2019-04-11,enjoyable
2019-04-12,enjoyable
2019-04-13,unenjoyable
2019-04-14,enjoyable
2019-04-15,unenjoyable
2019-04-16,unenjoyable
2019-04-17,unenjoyable
2019-04-18,enjoyable
2019-04-19,unenjoyable
2019-04-20,unenjoyable
2019-04-21,unenjoyable
2019-04-22,unenjoyable
2019-04-23,unenjoyable
2019-04-24,unenjoyable
2019-04-25,unenjoyable
2019-04-26,unenjoyable

La première partie du code fonctionne sans aucun problème, mais dans la deuxième partie, je ne sais pas comment obtenir les données de la première ligne (j'utilise donc dates [first_row] pour désigner la première ligne de la variable dates) à partir de la variable "dates" afin que nous puissions appliquer la méthode 'date' dessus

Et pour la troisième partie, je veux fusionner ces deux tableaux ensemble. J'ai trouvé la fonction 'join' mais elle semble fonctionner sur deux fichiers au lieu de deux variables (je ne veux pas avoir de nouveaux fichiers pendant le processus)

Quelqu'un pourrait-il me dire comment obtenir les lignes dans une variable au lieu d'un fichier dans le shell et comment fusionner deux variables de type table?


1 commentaires

En général, lundi est le jour numéro 1. Avec % w , dimanche est le jour 0; avec % u , dimanche est le jour 7.


3 Réponses :


3
votes

Avec GNU awk:

awk' BEGIN{FS=OFS=","}
     { split($1,a,"-")
       t=sprintf("%0.4d %0.2d %0.2d 00 00 00",a[1],a[2],a[3]);
       print $0,strftime("%w",mktime(t))
     }' file.csv


6 commentaires

Merci, mais est-il possible d'appliquer des méthodes shell dans des variables au lieu de fichiers? comme join $ var1 $ var2


@YilingLiu Je ne suis pas votre question. Vous avez un fichier CSV et vous voulez cette sortie. Pourquoi voulez-vous utiliser des variables shell? De plus, la commande join fonctionne avec les fichiers donc $ var1 et $ var2 doivent être des fichiers,


En outre, le format de l'heure vient en premier: gnu.org/software/ gawk / manual / html_node / Time-Functions.html


Je suis un nouvel apprenant shell et j'avais l'habitude d'utiliser python avant. Je pensais que l'utilisation de la variable pour stocker les résultats de la commande précédente est beaucoup plus facile à comprendre pour moi


Pas si: awk 'BEGIN {print mktime ("2019 04 26 01 02 03"); print mktime ("2019 4 26 1 2 3")} '


@YilingLiu vous devriez VRAIMENT utiliser GNU awk pour cela plutôt qu'une boucle shell. voir unix.stackexchange.com/q/169716/133219 .



3
votes

Alors que vous apprenez le script shell, voici du code à étudier:

  1. pour lire votre fichier csv et obtenir le numéro de la semaine pour chaque date du fichier:

    join -t, file.csv <(
        while IFS=, read -r date rest; do echo "$date,$(date -d "$date" +%w)"; done < file.csv
    )
    
  2. pour joindre la sortie de cette commande à votre fichier:

    weekdays=$(while IFS=, read -r date rest; do echo "$date,$(date -d "$date" +%w)"; done < file.csv)
    join -t, file.csv <(echo "$weekdays")
    

    ou, sans avoir besoin de stocker le résultat dans une variable intermédiaire

    while IFS=, read -r date rest; do echo "$date,$(date -d "$date" +%w)"; done < file.csv
    

    Les retours à la ligne dans ne sont pas nécessaires, mais utiles pour le code maintenable.

Cependant, vous pouvez voir que cela est moins efficace car vous devez traiter le fichier deux fois. Avec awk, vous n'avez à lire le fichier qu'une seule fois.


0 commentaires

1
votes

Avec uniquement votre Bourne shell, donc moins efficace que awk si vous avez beaucoup de lignes dans votre fichier CSV:

while IFS=, read date enjoy; do
    date -d "$date" +"$date,$enjoy,%w"
done < your.csv


2 commentaires

J'éviterais de mettre les variables au format de date: que se passe-t-il si certains formateurs de % X se retrouvent dans le fichier csv? Plus robuste à utiliser echo ou printf`


Je suppose que le format des lignes CSV est comme indiqué dans la question: YYYY-M [M] -D [D], [un] agréable . Si vous commencez à supposer le contraire, par exemple que les dates peuvent contenir des caractères étranges, aucune des réponses ne sera valide.