gawk / awk: * manchmal Datum getline kochend * wird nicht funktionieren
Frage
Ich versuche, stammt aus einem Format in ein anderes zu konvertieren: Von z.B. „29. Oktober 2005“ bis 2005-10-29. Ich habe eine Liste von 625 Terminen. Ich benutze Awk.
Die Umbauarbeiten - die meiste Zeit. Hovewer, manchmal wird die Umwandlung nicht passieren, und die Variable soll die (umgerechnet) Datum bleibt halten nicht definiert.
Dies geschieht immer mit den exakt gleichen Zeilen. Lauf `date‘ explizit (von der Bash-Shell) für die Tage, diese seltsamen Zeilen funktioniert gut (die Daten ordnungsgemäß umgesetzt werden). -. Es ist nicht die Textinhalte dieser Zeilen, dass Angelegenheiten
Warum dieses Verhalten, und wie kann ich mein Skript zu beheben?
Sie ist es:
awk 'BEGIN { FS = "unused" } {
x = "undefined";
"date \"+%Y-%m-%d\" -d " $1 | getline x ;
print $1 " = " x
}' uBXr0r15.txt \
> bug-out-3.txt
Wenn Sie möchten, um dieses Problem zu reproduzieren:
- Diese Datei herunterladen. uBXr0r15.txt
- Führen Sie den awk Skript.
- Suche nach "undefined" in Bug-out-3.txt.
( "Undefined" gefunden 122 mal, auf meinem Computer.)
Dann könnten Sie das Skript erneut ausführen, und (auf meinem Computer) bug-out-3.txt bleibt unverändert -. genau die gleichen Daten nicht definiert sind links
(Gawk Version 3.1.6, Ubuntu 9.10.)
Mit freundlichen Grüßen Magnus
Lösung
Wenn Sie ein Rohr oder eine Datei öffnen zum Lesen oder in awk
Schreiben, letztere wird zunächst prüfen, (über eine interne Hash) , ob es bereits eine Pfeife oder eine Datei mit dem gleichen Namen (noch) offen ist; wenn ja, es wird die vorhandene Datei-Descriptor Wiederverwendung , anstatt das Rohr oder die Datei wieder zu öffnen.
In Ihrem Fall, werden alle Einträge, die als undefined
am Ende tatsächlich dupliziert; das erste Mal, dass sie (erster ausgegeben wird, das heißt, wenn der entsprechende Befehl date "..." -d "..."
) das richtige Ergebnis wird in x
gelesen angetroffen werden. Bei nachfolgenden Vorkommen des gleichen Zeitpunkt, zu lesen getline
Versuche, eine zweiten, dritte usw. Linien von dem ursprünglichen date
Rohr, auch wenn das Rohr durch date
geschlossen wurde, was zu einer x
nicht mehr zugeordnet werden.
Von der gawk
Mann-Seite:
Hinweis: Bei Verwendung eines Rohres, Co-Prozess oder Buchse getline oder von Druck- oder printf innerhalb einer Schleife, Sie müssen close () verwenden, um neue zu erstellen Instanzen des Befehls oder Sockel. AWK nicht automatisch enge Rohre, Muffen, oder Co-Prozesse wenn sie EOF zurück.
Sie sollten das Rohr ausdrücklich close
jedes Mal, nachdem Sie x
gelesen haben:
close("date \"+%Y-%m-%d\" -d " $1)
Im übrigen wäre es OK, um sort
und uniq
uBXr0r15.txt
sein, bevor sie in awk
kochend, oder haben Sie die ursprüngliche Bestellung / Vervielfältigung müssen?
Andere Tipps
Obwohl ich liebe awk es ist nicht notwendig, für diese.
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
wird alles tun, innerhalb gaffen schneller als externe Befehle aufrufen.