gawk / awk:tubazioni data di getline *a volte* non funziona
Domanda
Sto tentando di convertire le date da un formato ad un altro:Per esempio"29 ottobre 2005" per 2005-10-29.Ho un elenco di 625 date.Io uso Awk.
La conversione funziona-la maggior parte del tempo.Ma io, a volte la conversione non capita a tutti, e la variabile dovrebbe tenere l' (convertito) data rimane non definito.
Questo accade sempre con le stesse righe.L'esecuzione di `data' esplicitamente (dalla shell Bash) nelle date di di quelle strane righe funziona bene (le date sono opportunamente convertiti).- Non è il contenuto testuale di quelle righe che conta.
Perché di questo comportamento e come posso risolvere il mio script?
Lei è:
awk 'BEGIN { FS = "unused" } {
x = "undefined";
"date \"+%Y-%m-%d\" -d " $1 | getline x ;
print $1 " = " x
}' uBXr0r15.txt \
> bug-out-3.txt
Se si desidera riprodurre il problema:
- Scarica questo file: uBXr0r15.txt.
- Eseguire lo script Awk.
- Ricerca di "indefinito" in bug-out-3.txt.
("undefined" trovati 122 volte, sul mio computer).
Quindi è possibile eseguire nuovamente lo script, e (sul mio computer) bug-out-3.txt rimane invariato-esattamente la stesse date sono lasciati indefiniti.
(Gawk versione 3.1.6, Ubuntu 9.10.)
Cordiali saluti, Magnus
Soluzione
Ogni volta che si apre un tubo o un file per la lettura o la scrittura in awk
, l'ultimo innanzitutto controlla (utilizzando un hash interno) se si dispone già di un tubo o un file con lo stesso nome (ancora) aperta;se è così, esso è in grado di riutilizzare l'esistente descrittore di file invece di riaprire il tubo o il file.
Nel tuo caso, tutte le voci che finiscono undefined
in realtà sono duplicati;la prima volta che si sono incontrati (es.quando il comando corrispondente date "..." -d "..."
è rilasciato per la prima volta) il risultato corretto è leggere in x
.Nelle successive occorrenze della stessa data, getline
tenta di leggere un secondo, terzo e così via.linee originali date
il tubo, anche se il tubo è stato chiuso da date
, con conseguente x
non è più assegnato.
Dal gawk
uomo-pagina:
NOTA:Se si utilizza un tubo, co-processo, o presa per getline, o da stampare o printf all'interno di un ciclo, è necessario utilizzare close() per creare nuove le istanze di comando o socket.AWK non automaticamente chiudere i tubi, prese di corrente, o co-processi quando si ritorna EOF.
In modo esplicito close
il tubo ogni volta dopo aver letto x
:
close("date \"+%Y-%m-%d\" -d " $1)
Per inciso, sarebbe OK per sort
e uniq
uBXr0r15.txt
prima di tubazioni in awk
, o avete bisogno di ordinamento originale/duplicazione?
Altri suggerimenti
Anche se io amo il awk non è necessario per questo.
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
facendo tutto all'interno di gawk sarà più chiamata comandi esterni.