Pergunta

Estou tentando converter datas de um formato para outro: de EG "29 de outubro de 2005" a 2005-10-29. Eu tenho uma lista de 625 datas. Eu uso awk.

A conversão funciona - na maioria das vezes. Hovewer, às vezes a conversão não acontece, e a variável deve manter a data (convertida) permanece indefinida.

Isso sempre acontece com as mesmas linhas exatamente. Executando a `date 'explicitamente (do shell Bash) nas datas dessas linhas estranhas funciona bem (as datas são adequadamente convertidas). - Não é o conteúdo textual das linhas que importa.

Por que esse comportamento e como posso consertar meu script?
Ela é:

awk 'BEGIN { FS = "unused" } { 
  x = "undefined";
  "date \"+%Y-%m-%d\" -d " $1 | getline x ;
  print $1 " = " x
}' uBXr0r15.txt \
 > bug-out-3.txt

Se você deseja reproduzir esse problema:

  1. Baixe este arquivo: ubxr0r15.txt.
  2. Execute o Skript Awk.
  3. Pesquise "indefinido" no bug-out-3.txt.
    ("indefinido" encontrado 122 vezes, no meu computador.)

Em seguida, você pode executar o script novamente e (no meu computador) Bug-Out-3.txt permanece inalterado-exatamente as mesmas datas são deixadas indefinidas.

(Gawk versão 3.1.6, Ubuntu 9.10.)

Atenciosamente, Magnus

Foi útil?

Solução

Sempre que você abre um tubo ou arquivo para ler ou escrever em awk, o último Vai primeiro verificar (usando um hash interno) se já tem um tubo ou arquivo com o mesmo nome (Ainda aberto; se for assim, Ele reutilizará o descritor de arquivo existente em vez de reabrir o tubo ou arquivo.

No seu caso, todas as entradas que acabam como undefined são realmente duplicatas; a primeira vez que eles são encontrados (ou seja, quando o comando correspondente date "..." -d "..." é emitido pela primeira vez) o resultado adequado é lido em x. Nas ocorrências subsequentes da mesma data, getline tentativas de ler uma segunda, terceira etc. linhas do original date tubo, mesmo que o tubo tenha sido fechado por date, resultando em x não está mais sendo atribuído.

De gawk Homem-página:

NOTA: Se estiver usando um tubo, co-processamento ou soquete para obter linha ou de impressão ou imprimir em um loop, você deve usar o fechamento () para criar novas instâncias do comando ou soquete. O AWK não fecha automaticamente tubos, soquetes ou co-processos quando retornam o EOF.

Você deve explicitamente close o cano toda vez que você lê x:

close("date \"+%Y-%m-%d\" -d " $1)

Aliás, seria bom sort e uniq uBXr0r15.txt antes de se deparar awk, ou você precisa do pedido/duplicação original?

Outras dicas

Embora eu ame awk, não é necessário para isso.

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

Fazer tudo dentro do Gawk será mais rápido do que chamar comandos externos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top