converter campo de coluna de arquivo de texto com dados dd.mm.aa para dd.mm.YYYY

-1

Como formatar a data para o conteúdo do arquivo usando as ferramentas de linha de comando do Linux?

Entrada:
aaa; 1,70; ccc; 20.01.13; zz; 2013;
uuu; 2.70; lll; 17.12.10; zz; 2013;
fff; 3,70; nnn; 31.01.98; zz; 2013;
auu; 8,70; nu; 30,02,96; zz; 2013;

Saída:
aaa; 1,70; ccc; 20.01.2013; zz; 2013;
uuu; 2.70; lll; 17.12.2010; zz; 2013;
fff; 3,70; nnn; 31; 01,1998; zz; 2013;
auu; 8, 70; nuu; 30.02.1996; zz; 2013;

Maris
fonte

Respostas:

0

Supondo que qualquer ano de dois dígitos entre 70 e 99 ocorra no século passado:

sed 's/[7-9][0-9];$/19&/; s/[0-6][0-9];$/20&/' file

Ou deixe alguém decidir:

perl -MTime::Piece -F';' -ane '
    $F[-2] = Time::Piece->strptime($F[-2], "%d.%m.%y")->strftime("%d.%m.%Y");
    print join(";", @F)
' file

Opções

  • -MTime::Piece importa o padrão Perl Relógio módulo
  • -F';' -a as opções dividem cada linha por ponto e vírgula e armazenam o resultado no @F matriz
  • -n faz um loop sobre as linhas nos dados de entrada (stdin ou arquivos) sem imprimir automaticamente cada linha.

Código

  • $F[-2] é o 2º último campo (que é onde a data estava em sua pergunta original).
  • Eu uso o strptime e strftime métodos para analisar e formatar a data.

Portanto, se você tiver datas que devem ser alterações nas colunas de 12 a 15, use

perl -MTime::Piece -F';' -ane '
    sub reformat {
        return Time::Piece->strptime(shift, "%d.%m.%y")->strftime("%d.%m.%Y");
    }
    for my $i (11..14) {
        $F[$i] = reformat $F[$i];
    }
    print join(";", @F)
' file
glenn jackman
fonte
Você pode comentar como isso funciona? Ele faz bem com o exemplo, mas quando eu coloco uma linha mais longa com várias datas, de alguma forma dá 01.01.1970 no final da linha. Gostaria que ele alterasse o formato de data para a coluna que é o número 12. e depois da coluna 12 existam outras 10 colunas. As datas devem ser alteradas na coluna 12 e 15. Outros campos / colunas não devem ser alterados.
Maris
Funciona como charme! Só eu separei para o meu $ i (11) e segunda vez eu levo para o meu $ i (14), não funcionou em conjunto 11..14, erro de análise de tempo em /usr/lib/perl/5.14/Time/Piece.pm linha 469, & lt; & gt; linha 1.:)
Maris
0

Isso pode ser feito com awk:

   awk -F'[;.]' '{if ($6 <= 13) x=20$6; else x = 19$6 ; print \
                  $1";"$2";"$3";"$4"."$5"."x";"}' 

Este comando separa campos com separadores ; e .. Em seguida, modifica o último campo desta maneira: se for menor ou igual a 13, é transformado em 20last_field, caso contrário, é transformado em 19last_filed, em seguida, imprime os campos na mesma ordem que antes, com os mesmos separadores, incluindo o sexto campo modificado (agora chamado x ).

MariusMatutiae
fonte
Esta poderia ser uma boa solução também, mas o problema é que os campos não podem ser separados com "." porque às vezes pode haver alguma informação com um ponto antes de $ 6 e será contada de forma errada.
Maris
@Maris Você deveria ter dito isso no OP.
MariusMatutiae
0

Usando dconv de dateutils :

dconv -Si '%d.%m.%y' -f '%d.%m.%Y' <<EOF
aaa;1.70;ccc;20.01.13;zz;2013;
uuu;2.70;lll;17.12.10;zz;2013;
fff;3.70;nnn;31.01.98;zz;2013;
auu;8.70;nuu;30.02.96;zz;2013;
EOF

produz exatamente a saída desejada.

hroptatyr
fonte