Esiste un’utilità Unix per anteporre i timestamp allo stdin?

Ho finito per scrivere un breve script per questo in Python, ma mi stavo chiedendo se ci fosse un’utilità da inserire nel testo che anteponesse ogni riga con del testo – nel mio caso specifico, un timestamp. Idealmente, l’uso sarebbe qualcosa di simile:

cat somefile.txt | prepend-timestamp 

(Prima di rispondere a sed, ho provato questo:

 cat somefile.txt | sed "s/^/`date`/" 

Ma questo valuta solo il comando date una volta quando viene eseguito sed, quindi lo stesso timestamp viene inserito in modo errato su ciascuna riga.)

Potrebbe provare a utilizzare awk :

  | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }' 

Potrebbe essere necessario assicurarsi che produca output di buffer di linea, ovvero svuota il stream di output dopo ogni linea; il timestamp awk aggiunge sarà il tempo in cui la fine della riga è comparsa sul suo tubo di input.

Se awk mostra errori, prova invece gawk .

ts from moreutils antepone un timestamp a ogni riga di input che gli dai. Puoi formattarlo anche con 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 $ 

Per installarlo:

 sudo apt-get install moreutils 

annotate , disponibili tramite quel link o come annotate-output nel pacchetto devscripts Debian.

 $ 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 

Distillare le risposte date al più semplice ansible:

 unbuffer $COMMAND | ts 

Su Ubuntu provengono dai pacchetti expect-dev e moreutils.

 sudo apt-get install expect-dev moreutils 

Cosa ne pensi di questo?

 cat somefile.txt | perl -pne 'print scalar(localtime()), " ";' 

A giudicare dal tuo desiderio di ottenere timestamp dal vivo, forse vuoi fare un aggiornamento live su un file di registro o qualcosa del genere? Può essere

 tail -f /path/to/log | perl -pne 'print scalar(localtime()), " ";' > /path/to/log-with-timestamps 

Lo farò qui: ci sono un paio di utility in daemontools chiamate tai64n e tai64nlocal create per preporre timestamp per registrare i messaggi.

Esempio:

 cat file | tai64n | tai64nlocal 

La risposta di Kieron è la migliore finora. Se si verificano problemi poiché il primo programma viene sottoposto a buffering, è ansible utilizzare il programma unbuffer:

 unbuffer  | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }' 

È installato di default sulla maggior parte dei sistemi Linux. Se hai bisogno di costruirlo da solo, fa parte del pacchetto previsto

http://expect.nist.gov

Utilizzare il comando di lettura (1) per leggere una riga alla volta dall’input standard, quindi inviare la riga preceduta dalla data nel formato desiderato utilizzando la data (1).

 $ cat timestamp #!/bin/sh while read line do echo `date` $line done $ cat somefile.txt | ./timestamp 

Non sono un ragazzo Unix, ma penso che tu possa usare

 gawk '{print strftime("%d/%m/%y",systime()) $0 }' < somefile.txt 
 #! /bin/sh unbuffer "[email protected]" | perl -e ' use Time::HiRes (gettimeofday); while(<>) { ($s,$ms) = gettimeofday(); print $s . "." . $ms . " " . $_; }' 

Ecco la mia soluzione awk (da un sistema Windows / XP con MKS Tools installato nella directory C: \ bin). È progettato per aggiungere la data e l’ora correnti nel formato mm / gg hh: mm all’inizio di ogni riga dopo aver recuperato il timestamp dal sistema durante la lettura di ogni riga. Ovviamente potresti usare il pattern BEGIN per recuperare il timestamp una volta e aggiungere quel timestamp a ogni record (lo stesso). Ho fatto questo per taggare un file di log che veniva generato per lo stdout con il timestamp nel momento in cui il messaggio di log è stato generato.

/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | getline timestamp;
print timestamp, $0;

dove “pattern” è una stringa o un’espressione regolare (senza virgolette) da corrispondere nella riga di input ed è facoltativa se si desidera abbinare tutte le linee di input.

Questo dovrebbe funzionare anche sui sistemi Linux / UNIX, basta sbarazzarsi di C \: \\ bin \\ lasciando la linea

  "date '+%m/%d %R'" | getline timestamp; 

Questo, naturalmente, presuppone che il comando “data” ti porti al comando standard di visualizzazione / set di date Linux / UNIX senza informazioni specifiche sul percorso (cioè, la variabile PATH dell’ambiente è configurata correttamente).

Mescolando alcune risposte sopra da Natevw e Frank Ch. Eigler.

Ha millisecondi, si comporta meglio di chiamare un comando date esterno ogni volta e perl può essere trovato nella maggior parte dei server.

 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); ' 

Versione alternativa con flush e read in 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); }' 

La risposta di caerwyn può essere eseguita come una subroutine, che impedirebbe i nuovi processi per riga:

 timestamp(){ while read line do echo `date` $line done } echo testing 123 |timestamp 

Disclaimer : la soluzione che sto proponendo non è un’utilità integrata Unix.

Ho affrontato un problema simile qualche giorno fa. Non mi piacevano la syntax e le limitazioni delle soluzioni di cui sopra, quindi ho rapidamente messo insieme un programma in Go per fare il lavoro per me.

Puoi controllare lo strumento qui: preorario

Esistono programmi eseguibili preinstallati per Linux, MacOS e Windows nella sezione Releases del progetto GitHub.

Lo strumento gestisce le righe di output incomplete e ha (dal mio punto di vista) una syntax più compatta.

| preftime

Non è l’ideale, ma io lo condividerei nel caso in cui aiutasse qualcuno.

 $ cat somefile.txt | sed "s/^/`date`/" 

puoi farlo (con gnu / sed ):

 $ some-command | sed "x;s/.*/date +%T/e;G;s/\n/ /g" 

esempio:

 $ { echo 'line1'; sleep 2; echo 'line2'; } | sed "x;s/.*/date +%T/e;G;s/\n/ /g" 20:24:22 line1 20:24:24 line2 

ovviamente, puoi usare altre opzioni della data del programma. basta sostituire la date +%T con quello che ti serve.

farlo con date e tr e xargs su OSX:

 alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S\" | tr \"\n\" \" \"; echo \"{}\"'"  | predate 

se vuoi millisecondi:

 alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'" 

ma nota che su OSX, data non ti dà l’opzione% N, quindi dovrai installare gdate ( brew install coreutils ) e così alla fine arriverai a questo:

 alias predate="xargs -I{} sh -c 'gdate +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'" 

Se il valore che prependi è lo stesso su ogni riga, triggers emacs con il file, quindi:

Ctrl +

all’inizio del file (per contrassegnare quel punto), quindi scorrere verso il basso fino all’inizio dell’ultima riga (Alt +> andrà alla fine del file … che probabilmente coinvolgerà anche il tasto Maiusc, quindi Ctrl + a per andare all’inizio di quella linea) e:

Ctrl + x r t

Qual è il comando da inserire nel rettangolo appena specificato (un rettangolo di larghezza 0).

2008-8-21 6:45 PM

O qualsiasi cosa tu voglia anteporre … allora vedrai che il testo è anteposto a ogni riga all’interno del rettangolo di larghezza 0.

AGGIORNAMENTO: Ho appena realizzato che non vuoi la data SAME, quindi non funzionerà … anche se potresti essere in grado di farlo in emacs con una macro personalizzata leggermente più complicata, ma comunque, questo tipo di modifica del rettangolo è carino da sapere su …