web-dev-qa-db-fra.com

Conversion de dates en AWK

J'ai un fichier contenant plusieurs colonnes de texte, y compris un horodatage du type Fri Jan 02 18:23 et je dois convertir cette date au format MM/DD/YYYY HH:MM.

J'ai essayé d'utiliser l'outil standard `date 'avec awk getline pour effectuer la conversion, mais je ne vois pas très bien comment passer les champs à la commande' date 'dans le format attendu (cité avec" ou " s,) comme getline a également besoin de la chaîne de commande entre guillemets.

Quelque chose comme "date -d '$1 $2 $3 $4' +'%D %H:%M'" | getline var

Maintenant que j'y pense, je suppose que ce que je demande vraiment, c'est comment intégrer des variables awk dans une chaîne.

17
PStibbons

vous pouvez essayer ça. En supposant que la date spécifiée soit dans le fichier

awk '
{
    cmd ="date \"+%m/%d/%Y %H:%M\" -d \""$1" "$2" "$3" "$4"\""
    cmd | getline var
    print var
    close(cmd)
}' file

sortie

$ ./Shell.sh
01/02/2010 18:23

et si vous n'utilisez pas les outils GNU, comme si vous utilisiez Solaris par exemple, utilisez nawk.

nawk 'BEGIN{
   m=split("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec",d,"|")
   for(o=1;o<=m;o++){
      months[d[o]]=sprintf("%02d",o)
   }
   cmd="date +%Y"
   cmd|getline yr
   close(cmd)
}
{
    day=$3
    mth=months[$2]
    print mth"/"day"/"yr" "$4
} ' file
17
ghostdog74

Si vous utilisez gawk, vous n'avez pas besoin de la variable date externe qui peut être coûteuse pour appeler plusieurs fois:

awk '
BEGIN{
   m=split("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec",d,"|")
   for(o=1;o<=m;o++){
      months[d[o]]=sprintf("%02d",o)
    }
format = "%m/%d/%Y %H:%M"
}
{
split($4,time,":")
date = (strftime("%Y") " " months[$2] " " $3 " " time[1] " " time[2] " 0")
print strftime(format, mktime(date))
}'

Merci à ghostdog74 pour le tableau des mois de cette réponse .

21
Dennis Williamson

J'ai eu un problème similaire lors de la conversion d'une date à partir de bases de données RRDTool à l'aide de rrdfetch, mais je préfère l'un des liners que j'utilise depuis l'époque informatique Apollo.

Les données ressemblaient à ceci:

localTemp             rs1Temp             rs2Temp      thermostatMode
1547123400: 5.2788174937e+00 4.7788174937e+00 -8.7777777778e+00 2.0000000000e+00
1547123460: 5.1687014581e+00 4.7777777778e+00 -8.7777777778e+00 2.0000000000e+00

Bon mot:

rrdtool fetch -s -14400 thermostatDaily.rrd MAX | sed s/://g | awk '{print "echo ""\`date -r" $1,"\`" " " $2 }' | sh

Résultat:

Thu Jan 10 07:25:00 EST 2019 5.3373432378e+00
Thu Jan 10 07:26:00 EST 2019 5.2788174937e+00

À première vue, cela ne me semble pas très efficace, mais ce type de méthodologie s'est toujours avéré être relativement peu onéreux dans la plupart des cas, même pour des fichiers très volumineux sur un ordinateur à très faible consommation (comme les machines à 25 MHz de NeXT). Oui mhz.

Sed supprime les deux points, awk est utilisé pour imprimer les autres commandes d’intérêt, notamment le renvoi en écho des variables awk, et sh ou bash exécute la chaîne résultante.

Pour la méthodologie ou les gros fichiers ou flux, je me contente de diriger les premières lignes et de construire progressivement la couche. Jeter le code.

0
Ian Jefferson