Como prefixar uma linha lida de STDIN com um registro de data e hora de época? [duplicado]

1
    

Esta pergunta já tem uma resposta aqui:

    

Eu estou querendo preceder o tempo da época para uma única linha de argumentos. Minha saída desejada é:

$ echo foo bar baz | some_bash_awk_sed_date_program_or_something_else
1491146539 foo bar baz

A saída real que estou recebendo pode ser vista abaixo:

$ echo foo bar baz | awk -f time_stamper.awk
1491146539
0 foo bar baz

Meu time_stamper.awk :

BEGIN { 
OFS=" "
printf "%s ", system("date +'%s'")
}
{ print }

Acho que o principal 0 é proveniente do valor de retorno de date +'%s' . Eu estava esperando definir o OFS=" " pelo menos retornaria 1491146539 0 foo bar baz alterando a nova linha para o espaço.

Algumas perguntas sobre minha tentativa atual:

Mais importante, não sei se awk é a ferramenta certa para o trabalho. Talvez eu deva usar sed , date ou algum outro utilitário.

  • Como imprimo a saída desejada?

Nota: Esta questão é mais específica e, portanto, diferente de esta questão . Além disso, a resposta requer a instalação de moreutils que parece ser uma adição interessante ao conjunto de ferramentas Unix; no entanto, prefiro ficar com utilitários Unix mais tradicionais para executar minha tarefa.

    
por mbigras 02.04.2017 / 17:32

3 respostas

5

A função system() em awk executa o comando e retorna seu status. Você tem 0 porque o comando é sucesso. A saída de date +'%s' foi impressa separadamente.

Para obter a saída do comando externo, use getline () :

$ echo foo bar baz | awk '{"date +%s" | getline d; printf "%s %s\n", d, $0}'
1491147643 foo bar baz

Não há nada a ver com OFS , porque é um espaço por padrão.

Com gawk ou mawk , você também pode fazer:

echo foo bar baz | gawk '{printf "%s %s\n", systime(), $0}'

O systime() retorna o número de segundos desde a época, sem contar os segundos de salto

IOW, você pode fazer isso sozinho com date :

date +'%s foo bar baz'
    
por 02.04.2017 / 17:41
2

Bash
Aqui nós usamos um laço while para ingerir os argumentos de stdin & não execute divisão, pois usamos IFS= com read . Isso permite que toda a linha com o espaço em branco concomitante seja preservada. E finalmente, nós echo the timestamp juntamente com os argumentos agora disponíveis através da variável $l . Um ponto a ser lembrado é que todos os argumentos para echo precisam ser citados quanto ao comportamento previsível do código.

echo 'foo     bar baz' | while IFS= read -r l; do echo "$(date +'%s')" "$l"; done

Perl

A opção

-n instrui Perl a ler um arquivo linha por linha + não imprimir, a menos que especificamente solicitado. Cada linha lida é armazenada no $_ , que é equivalente a $0 de awk . time() é uma função Perl builtin para nos fornecer o epoch time. Em seguida, colocamos o horário da época e a linha atual em uma referência anonymous da matriz [ ..., ... ] e recuperamos o conteúdo dessa matriz por dereferencing it, @{ ... } As aspas duplas "..." em torno da expressão @{...} garantem que os elementos da lista devem ser separados por espaços. Então nós os imprimimos.

echo ... |  perl -ne 'print "@{[+time,$_]}"'

IFS= read -r l <<<"$(echo 'foo    bar baz')"
printf '%d %s\n' "$(date +'%s')" "$l"
    
por 02.04.2017 / 18:45
1

Isso também pode ser feito com o sed

Código:

 echo 1 2 3 | sed 's/^/''date +"%s"'' /'

Resultados:

1491148928 1 2 3
    
por 02.04.2017 / 18:04