Ajusta informações de data e hora dentro de vários arquivos de texto automaticamente a partir da linha de comando

0

Eu tenho uma pasta com vários arquivos de texto cujo conteúdo é algo assim:

text text
more text
Date: Thu, 31 Dec 2015 23:53:51 +0000 (UTC)
more text
some more

Eu quero que a data e a hora estejam corretas de acordo com meu fuso horário (no meu caso, se houver "+0000 (UTC)", preciso adicionar 1 hora para o horário de inverno)

Portanto, o resultado deve ser o mesmo arquivo (mesmo nome de arquivo ou se você deseja "arquivo_adicional_original nome_do_arquivo") contendo:

text text
more text
Date: Fri, 1 Jan 2016 00:53:51
more text
some more

Observe que a linha que precisa ser editada começa com "Data:" (que é única, não há outra "Data:" no arquivo de texto) e termina em "+0000 (UTC)". E só será editado se o final da linha for "+0000 (UTC)".

Entre esses arquivos eu tenho outros:

text text
text text
Date: Mon, 12 Oct 2015 23:07:29 +0200
text text
text text

Eles não precisam ser ajustados (na verdade, eu gostaria que o "+0200" fosse removido).

Essas correções seriam feitas automática e periodicamente para todos os arquivos contidos em "/ home / user / folder01" (por exemplo, eu não estou na frente deste computador). Estou executando o Ubuntu 15.04.

    
por tom_len 16.10.2015 / 18:23

3 respostas

2

Você pode usar o GNU date para converter a hora em seu fuso horário local.

 awk '/^Date:.*UTC/ {cmd="date -Rd \"" substr($0,6) "\""; cmd | getline new; close(cmd); $0="Date: " new} 1' file
text text
more text
Date: Fri, 01 Jan 2016 01:53:51 +0200
more text
some more

Se você tiver o GNU awk, você pode alterar todos os arquivos no diretório atual usando:

gawk -i inplace '/^Date:.*UTC/ {cmd="date -Rd \"" substr($0,6) "\""; cmd | getline new; close(cmd); $0="Date: " new} 1' *

Sem o GNU awk, use:

for f in *
do
    awk '/^Date:.*UTC/ {cmd="date -Rd \"" substr($0,6) "\""; cmd | getline new; close(cmd); $0="Date: " new} 1' "$f" >tmp && mv tmp "$f"
done

Como funciona

  • -i inplace

    Isto diz ao GNU awk para alterar os arquivos no lugar. Isso requer um moderno GNU awk. Se você usar o awk de Mike, use o loop do bash como mostrado acima.

  • /^Date:.*UTC/ {cmd="date -Rd \"" substr($0,6) "\""; cmd | getline new; close(cmd); $0="Date: " new}

    Isso seleciona as linhas que começam com Date: e contêm UTC na mesma linha. Para essas linhas, o comando date -Rd é executado na parte da linha que contém a data. O resultado é armazenado na variável new . Então, a linha atual, denotada por $0 no awk, é substituída por uma com a nova data.

  • 1

    Esta é uma abreviada enigmática do awk para imprimir a linha.

Versão GNU de várias linhas

Se você preferir que seus scripts sejam distribuídos em várias linhas:

gawk -i inplace '

/^Date:.*UTC/ {
    cmd="date -Rd \"" substr($0,6) "\""; cmd | getline new
    close(cmd)
    $0="Date: " new
}

1
' file

Alguns refinamentos (versão não-GNU)

  1. O código acima procura linhas que começam com Date: e que também contêm as letras UTC . Isto parece-me bom o suficiente. A pergunta, no entanto, é mais específica para as linhas que iniciam Date: e terminam com +0000 (UTC) .

  2. A pergunta também pede para eliminar o +0200 à direita das linhas de data não UTC.

Adicionando esses dois refinamentos, o código se torna:

for f in *
do
    awk '/Date: .* [+]0200$/{sub(/ [+]0200$/,"")} /^Date: .* [+]0000 [(]UTC[)]$/ {cmd="date -Rd \"" substr($0,6) "\""; cmd | getline new; close(cmd); $0="Date: " new} 1' "$f" >tmp && mv tmp "$f"
done

Esse código é mais preciso, mas também mais perspicaz. Por exemplo, esse código insiste em que uma linha termine com +0000 (UTC) antes de alterá-la. Consequentemente, as linhas com espaços em branco à direita, que podem ser invisíveis em seu editor, não serão alteradas. Se isso é bom ou não é algo para você decidir.

    
por John1024 16.10.2015 / 18:50
0

Usando o Perl:

perl -pe 's/Date: (.* \+0000 \(UTC\))/$1/?$_="Date: ".'LC_TIME=en_US.UTF-8 date -d "$_" "+%a, %d %b %Y %T"':s/(Date:.*) \+[0-9]{4}/$1/' in
  • Se a substituição de s/Date: (.* \+0000 \(UTC\))/$1/ , que substitui toda a linha pela seção após Date: , puder ser feita, imprime Date: seguido pela saída de LC_TIME=en_US.UTF-8 date -d "$_" "+%a, %d %b %Y %T" , que converte a parte substituída no fuso horário atual usando um valor LC_TIME de en_US.UTF-8 ; caso contrário, se a substituição de s/(Date:.*) \+[0-9]{4}/$1/ , que substitui a linha inteira pela seção antes de +NNNN , puder ser feita, imprime a parte substituída; se nenhuma substituição puder ser feita, imprime a linha inteira.

Isso significa que o valor atual de LC_TIME está definido como en_US.UTF-8 (ou equivalente) já, a parte LC_TIME=en_US.UTF-8 é segura para ser descartada:

perl -pe 's/Date: (.* \+0000 \(UTC\))/$1/?$_="Date: ".'date -d "$_" "+%a, %d %b %Y %T"':s/(Date:.*) \+[0-9]{4}/$1/' in
% cat in
line
Date: Thu, 31 Dec 2015 23:53:51 +0000 (UTC)
Date: Mon, 12 Oct 2015 23:07:29 +0200
% perl -pe 's/Date: (.* \+0000 \(UTC\))/$1/?$_="Date: ".'LC_TIME=en_US.UTF-8 date -d "$_" "+%a, %d %b %Y %T"':s/(Date:.*) \+[0-9]{4}/$1/' in
line
Date: Fri, 01 Jan 2016 00:53:51
Date: Mon, 12 Oct 2015 23:07:29

Para editar o arquivo no local e aplicá-lo a vários arquivos, você pode adicionar a opção -i e passar * em vez do nome do arquivo:

% cat in
line
Date: Thu, 31 Dec 2015 23:53:51 +0000 (UTC)
Date: Mon, 12 Oct 2015 23:07:29 +0200
% cat in1
line
Date: Thu, 31 Dec 2015 23:53:51 +0000 (UTC)
Date: Mon, 12 Oct 2015 23:07:29 +0200
user@user-X550CL ~/tmp % perl -i -pe 's/Date: (.* \+0000 \(UTC\))/$1/?$_="Date: ".'LC_TIME=en_US.UTF-8 date -d "$_" "+%a, %d %b %Y %T"':s/(Date:.*) \+[0-9]{4}/$1/' *
user@user-X550CL ~/tmp % cat in
line
Date: Fri, 01 Jan 2016 00:53:51
Date: Mon, 12 Oct 2015 23:07:29
user@user-X550CL ~/tmp % cat in1
line
Date: Fri, 01 Jan 2016 00:53:51
Date: Mon, 12 Oct 2015 23:07:29
    
por kos 16.10.2015 / 20:16
0

perl para a exclusão e awk para a parte date . Substitua foo pelo seu nome de arquivo

perl -pe 's/^(Date:.*)\+[0-9]{4}$/$1/' foo | \
    awk -F'Date:' '/(UTC)/ {system("echo Date: $(date -d \""$2"\" +\"%a, %d %b %Y %H:%M:%S\") "); next} {print $0}'

Exemplo

cat dates

text text
more text
Date: Thu, 31 Dec 2015 23:53:51 +0000 (UTC)
more text
some more
text text
text text
Date: Mon, 12 Oct 2015 23:07:29 +0200
text text
text text
text text
more text
Date: Fri, 1 Jan 2016 01:53:51
more text
some more
perl -pe 's/^(Date:.*)\+[0-9]{4}$/$1/' dates | \
    awk -F'Date:' '/(UTC)/ {system("echo Date: $(date -d \""$2"\" +\"%a, %d %b %Y %H:%M:%S\") "); next} {print $0}'
text text
more text
Date: Fri, 01 Jan 2016 01:53:51
more text
some more
text text
text text
Date: Mon, 12 Oct 2015 23:07:29 
text text
text text
text text
more text
Date: Fri, 1 Jan 2016 01:53:51
more text
some more
    
por A.B. 16.10.2015 / 19:07