Existe um utilitário Unix para acrescentar carimbos de data/hora ao stdin?

StackOverflow https://stackoverflow.com/questions/21564

  •  09-06-2019
  •  | 
  •  

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.)

Foi útil?

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

http://expect.nist.gov

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 ...

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