Existe um utilitário Unix para acrescentar carimbos de data/hora ao stdin?
Pergunta
Acabei escrevendo um pequeno script rápido para isso em Python, mas queria saber se havia um utilitário no qual você pudesse inserir texto e acrescentar algum texto a cada linha - no meu caso específico, um carimbo de data / hora.Idealmente, o uso seria algo como:
cat somefile.txt | prepend-timestamp
(Antes de responder sed, tentei isto:
cat somefile.txt | sed "s/^/`date`/"
Mas isso avalia o comando date apenas uma vez quando sed é executado, portanto, o mesmo carimbo de data/hora é anexado incorretamente a cada linha.)
Solução
Poderia tentar usar awk
:
<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }'
Você pode precisar ter certeza de que <command>
produz saída com buffer de linha, ou seja,ele libera seu fluxo de saída após cada linha;o carimbo de data/hora awk
add será o horário em que o final da linha apareceu em seu pipe de entrada.
Se o awk mostrar erros, tente gawk
em vez de.
Outras dicas
ts
de maisutils irá anexar um carimbo de data/hora a cada linha de entrada que você fornecer.Você também pode formatá-lo usando strftime.
$ echo 'foo bar baz' | ts
Mar 21 18:07:28 foo bar baz
$ echo 'blah blah blah' | ts '%F %T'
2012-03-21 18:07:30 blah blah blah
$
Para instalá-lo:
sudo apt-get install moreutils
anotar, disponível através desse link ou como annotate-output
no Debian devscripts
pacote.
$ echo -e "a\nb\nc" > lines
$ annotate-output cat lines
17:00:47 I: Started cat lines
17:00:47 O: a
17:00:47 O: b
17:00:47 O: c
17:00:47 I: Finished with exitcode 0
Destilando as respostas dadas para as mais simples possíveis:
unbuffer $COMMAND | ts
No Ubuntu, eles vêm dos pacotes expect-dev e moreutils.
sudo apt-get install expect-dev moreutils
Que tal agora?
cat somefile.txt | perl -pne 'print scalar(localtime()), " ";'
A julgar pelo seu desejo de obter carimbos de data/hora ao vivo, talvez você queira fazer uma atualização ao vivo em um arquivo de log ou algo assim?Talvez
tail -f /path/to/log | perl -pne 'print scalar(localtime()), " ";' > /path/to/log-with-timestamps
Só vou jogar isso aí:há um par de utilitários em Daemon Tools chamado tai64n e tai64nlocal que são feitos para anexar carimbos de data/hora às mensagens de log.
Exemplo:
cat file | tai64n | tai64nlocal
A resposta de Kieron é a melhor até agora.Se você tiver problemas porque o primeiro programa está armazenando em buffer, você pode usar o programa unbuffer:
unbuffer <command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'
É instalado por padrão na maioria dos sistemas Linux.Se você precisar construí-lo sozinho, faz parte do pacote expect
Use o comando read(1) para ler uma linha por vez da entrada padrão e, em seguida, produza a linha anexada à data no formato de sua escolha usando date(1).
$ cat timestamp
#!/bin/sh
while read line
do
echo `date` $line
done
$ cat somefile.txt | ./timestamp
Não sou um cara do Unix, mas acho que você pode usar
gawk '{print strftime("%d/%m/%y",systime()) $0 }' < somefile.txt
#! /bin/sh
unbuffer "$@" | perl -e '
use Time::HiRes (gettimeofday);
while(<>) {
($s,$ms) = gettimeofday();
print $s . "." . $ms . " " . $_;
}'
Aqui está minha solução awk (de um sistema Windows/XP com MKS Tools instalado no diretório C:\bin).Ele foi projetado para adicionar a data e hora atuais no formato mm/dd hh:mm ao início de cada linha, obtendo esse carimbo de data/hora do sistema à medida que cada linha é lida.Você poderia, é claro, usar o padrão BEGIN para buscar o carimbo de data/hora uma vez e adicioná-lo a cada registro (todos iguais).Fiz isso para marcar um arquivo de log que estava sendo gerado para stdout com o carimbo de data/hora no momento em que a mensagem de log foi gerada.
/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | getline timestamp;
print timestamp, $0;
onde "pattern" é uma string ou regex (sem as aspas) a ser correspondida na linha de entrada e é opcional se você deseja corresponder a todas as linhas de entrada.
Isso também deve funcionar em sistemas Linux/UNIX, apenas livre-se do C\:\\bin\\ deixando a linha
"date '+%m/%d %R'" | getline timestamp;
Isso, é claro, pressupõe que o comando "date" leva você ao comando padrão de exibição/definição de data do Linux/UNIX sem informações de caminho específicas (ou seja, sua variável de ambiente PATH está configurada corretamente).
Misturando algumas respostas acima de natevw e Frank Ch.Eigler.
Tem milissegundos, tem desempenho melhor do que chamar um externo date
comando de cada vez e perl pode ser encontrado na maioria dos servidores.
tail -f log | perl -pne '
use Time::HiRes (gettimeofday);
use POSIX qw(strftime);
($s,$ms) = gettimeofday();
print strftime "%Y-%m-%dT%H:%M:%S+$ms ", gmtime($s);
'
Versão alternativa com flush e leitura em loop:
tail -f log | perl -pne '
use Time::HiRes (gettimeofday); use POSIX qw(strftime);
$|=1;
while(<>) {
($s,$ms) = gettimeofday();
print strftime "%Y-%m-%dT%H:%M:%S+$ms $_", gmtime($s);
}'
$ cat somefile.txt | sed "s/^/`date`/"
você pode fazer isso (com gnu/sed):
$ some-command | sed "x;s/.*/date +%T/e;G;s/\n/ /g"
exemplo:
$ { echo 'line1'; sleep 2; echo 'line2'; } | sed "x;s/.*/date +%T/e;G;s/\n/ /g"
20:24:22 line1
20:24:24 line2
claro, você pode usar outras opções do programa data.apenas substitua date +%T
com o que você precisa.
A resposta de caerwyn pode ser executada como uma sub-rotina, o que impediria novos processos por linha:
timestamp(){
while read line
do
echo `date` $line
done
}
echo testing 123 |timestamp
Isenção de responsabilidade:a solução que estou propondo não é um utilitário integrado do Unix.
Eu enfrentei um problema semelhante há alguns dias.Não gostei da sintaxe e das limitações das soluções acima, então montei rapidamente um programa em Go para fazer o trabalho para mim.
Você pode conferir a ferramenta aqui: pré-horário
Existem executáveis pré-construídos para Linux, MacOS e Windows no Lançamentos seção do projeto GitHub.
A ferramenta lida com linhas de saída incompletas e possui (do meu ponto de vista) uma sintaxe mais compacta.
<command> | preftime
Não é o ideal, mas gostaria de compartilhar caso ajude alguém.
fazendo isso com date
e tr
e xargs
no OSX:
alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S\" | tr \"\n\" \" \"; echo \"{}\"'"
<command> | predate
se você quiser milissegundos:
alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"
mas observe que no OSX, date não oferece a opção% N, então você precisará instalar o gdate (brew install coreutils
) e finalmente chegamos a isto:
alias predate="xargs -I{} sh -c 'gdate +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"
Se o valor que você está acrescentando for o mesmo em todas as linhas, inicie o emacs com o arquivo e então:
Ctrl + <espaço>
no início do arquivo (para marcar esse local) e, em seguida, role para baixo até o início da última linha (Alt + > irá para o final do arquivo...o que provavelmente envolverá a tecla Shift também, então Ctrl + a para ir para o início dessa linha) e:
Ctrl + x R t
Qual é o comando para inserir no retângulo que você acabou de especificar (um retângulo de largura 0).
21/08/2008 18h45 <entrar>
Ou o que você quiser acrescentar ...então você verá esse texto anexado a cada linha dentro do retângulo de largura 0.
ATUALIZAR:Acabei de perceber que você não quer a MESMA data, então isso não vai funcionar...embora você possa fazer isso no emacs com uma macro personalizada um pouco mais complicada, mas ainda assim, é muito bom conhecer esse tipo de edição de retângulo ...