gawk / awk: Date de tuyauterie getline * * parfois ne fonctionne pas
Question
Je tente de convertir les dates d'un format à l'autre: De par exemple « .29 Octobre 2005 » Représenter 2005-10-29. J'ai une liste de 625 dates. J'utilise awk.
Les travaux de conversion - la plupart du temps. Hovewer, parfois la conversion ne se produira pas du tout, et la variable censée contenir les restes de date (convertis) non défini.
Cela se produit toujours avec exactement les mêmes lignes. Exécution `date » explicitement (à partir du shell Bash) sur les dates de ces lignes étranges fonctionne très bien (les dates sont correctement converties). -. Ce n'est pas le contenu textuel de ces lignes qui compte
Pourquoi ce comportement, et comment puis-je réparer mon script?
Son est:
awk 'BEGIN { FS = "unused" } {
x = "undefined";
"date \"+%Y-%m-%d\" -d " $1 | getline x ;
print $1 " = " x
}' uBXr0r15.txt \
> bug-out-3.txt
Si vous voulez reproduire ce problème:
- Télécharger ce fichier:. uBXr0r15.txt
- Lancez le skript Awk.
- Rechercher "undefined" dans le bogue-out-3.txt.
(Trouvé 122 fois "non défini", sur mon ordinateur.)
Ensuite, vous pouvez exécuter à nouveau le script, et (sur mon ordinateur) reste bug-out-3.txt inchangé -. exactement les mêmes dates sont laissées undefined
(version 3.1.6 Gawk, Ubuntu 9.10.)
Cordialement, Magnus
La solution
Chaque fois que vous ouvrez un tube ou d'un fichier pour la lecture ou l'écriture dans awk
, ce dernier va d'abord vérifier (en utilisant un hachage interne) si elle a déjà un tuyau ou un fichier avec le même nom (encore) ouvert; le cas échéant, il réutiliser le descripteur de fichier existant au lieu de rouvrir le tuyau ou d'un fichier.
Dans votre cas, toutes les entrées qui finissent comme undefined
sont des doublons en fait; la première fois qu'ils sont rencontrés (à savoir lorsque le date "..." -d "..."
de commande correspondant est d'abord émis) le résultat correct est lu dans x
. Sur les occurrences suivantes de la même date, getline
tente de lire un deuxième, troisième lignes, etc. de la conduite de date
d'origine, même si le tube a été fermé par date
, ce qui x
ne sont plus affectés.
De l'homme gawk
page:
Remarque: Si l'on utilise un tuyau, co-processus, ou d'une douille à getline, ou d'impression ou printf dans une boucle, vous devez utiliser close () pour créer un nouveau cas de la commande ou de la douille. AWK ne pas automatiquement tubes étroits, des douilles, ou de co-processus quand ils reviennent EOF.
Vous devez close
explicitement le tuyau à chaque fois après avoir lu x
:
close("date \"+%Y-%m-%d\" -d " $1)
Soit dit en passant, serait-il sur OK pour sort
et uniq
uBXr0r15.txt
avant la tuyauterie en awk
, ou avez-vous besoin de la commande / duplication original?
Autres conseils
Bien que je l'aime awk il ne faut pas pour cela.
tr -d '"' < uBXr0r15.txt | date +%Y-%m-%d -f -
gawk 'BEGIN{
m=split("January|February|March|April|May|June|July|August|September|October|November|December",d,"|")
for(o=1;o<=m;o++){
months[d[o]]=sprintf("%02d",o)
}
FS="[, ]"
}
{
gsub(/["]/,"",$1)
gsub(/["]/,"",$4)
t=mktime($4" "months[$1]" "$2" 0 0 0")
print strftime("%Y-%m-%d",t)
}' uBXr0r15.txt
faire tout ce que l'intérieur gawk sera plus rapide que d'appeler des commandes externes.