Esiste un'utilità Unix per anteporre i timestamp a stdin?
Domanda
Ho finito per scrivere un piccolo script veloce per questo in Python, ma mi chiedevo se ci fosse un'utilità in cui potresti inserire del testo che anteponesse a ogni riga del testo - nel mio caso specifico, un timestamp.Idealmente, l'uso sarebbe qualcosa del tipo:
cat somefile.txt | prepend-timestamp
(Prima di rispondere a sed, ho provato questo:
cat somefile.txt | sed "s/^/`date`/"
Ma questo valuta il comando date solo una volta quando viene eseguito sed, quindi lo stesso timestamp viene anteposto erroneamente a ogni riga.)
Soluzione
Potrebbe provare a utilizzare awk
:
<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }'
Potrebbe essere necessario accertarsene <command>
produce un output con buffer di linea, ovveroscarica il flusso di output dopo ogni riga;il timestamp awk
aggiunge sarà l'ora in cui la fine della riga è apparsa sulla sua pipe di input.
Se awk mostra errori, prova gawk
Invece.
Altri suggerimenti
ts
da moreutils anteporrà un timestamp a ogni riga di input che gli fornisci.Puoi formattarlo anche 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
$
Per installarlo:
sudo apt-get install moreutils
annotare, disponibile tramite quel collegamento o come annotate-output
nella Debian devscripts
pacchetto.
$ 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
Distillando le risposte fornite in quella più semplice possibile:
unbuffer $COMMAND | ts
Su Ubuntu provengono dai pacchetti wait-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 in tempo reale, forse vuoi eseguire l'aggiornamento in tempo reale su un file di registro o qualcosa del genere?Forse
tail -f /path/to/log | perl -pne 'print scalar(localtime()), " ";' > /path/to/log-with-timestamps
Butterò semplicemente questo là fuori:ci sono un paio di utilità dentro strumenti del demonio chiamato tai64n E tai64nlocal creati per anteporre timestamp ai messaggi di registro.
Esempio:
cat file | tai64n | tai64nlocal
La risposta di Kieron è la migliore finora.Se hai problemi perché il primo programma sta esaurendo il buffer, puoi utilizzare il programma unbuffer:
unbuffer <command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'
È installato di default sulla maggior parte dei sistemi Linux.Se devi costruirlo da solo, fa parte del pacchetto wait
Utilizza il comando read(1) per leggere una riga alla volta dallo standard input, quindi visualizza la riga preceduta dalla data nel formato che preferisci utilizzando date(1).
$ cat timestamp
#!/bin/sh
while read line
do
echo `date` $line
done
$ cat somefile.txt | ./timestamp
Non sono un tipo Unix, ma penso che tu possa usarlo
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 . " " . $_;
}'
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 ciascuna riga.Potresti, ovviamente, utilizzare il modello BEGIN per recuperare il timestamp una volta e aggiungerlo a ciascun record (tutti uguali).L'ho fatto per contrassegnare un file di registro che veniva generato su stdout con il timestamp nel momento in cui è stato generato il messaggio di registro.
/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | getline timestamp;
print timestamp, $0;
dove "modello" è una stringa o una regex (senza virgolette) da abbinare nella riga di input ed è facoltativo se desideri abbinare tutte le righe di input.
Dovrebbe funzionare anche su sistemi Linux/UNIX, basta eliminare C\:\\bin\\ che lascia la riga
"date '+%m/%d %R'" | getline timestamp;
Ciò, ovviamente, presuppone che il comando "date" ti porti al comando standard di visualizzazione/impostazione della data Linux/UNIX senza informazioni sul percorso specifico (ovvero, la variabile PATH dell'ambiente è configurata correttamente).
Mescolando alcune risposte sopra da natevw e Frank Ch.Eigler.
Ha millisecondi, funziona meglio che chiamare un esterno date
comando ogni volta e perl possono essere trovati 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 lettura 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);
}'
$ 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 utilizzare altre opzioni del programma data.basta sostituire date +%T
con ciò di cui hai bisogno.
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 sintassi e le limitazioni delle soluzioni di cui sopra, quindi ho messo insieme rapidamente un programma in Go che svolgesse il lavoro per me.
Puoi controllare lo strumento qui: pre-orario
Sono disponibili eseguibili predefiniti per Linux, MacOS e Windows nel file Rilasci sezione del progetto GitHub.
Lo strumento gestisce righe di output incomplete e ha (dal mio punto di vista) una sintassi più compatta.
<command> | preftime
Non è l'ideale, ma ho pensato di condividerlo nel caso in cui aiuti qualcuno.
farlo con date
E tr
E xargs
su OS X:
alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S\" | tr \"\n\" \" \"; echo \"{}\"'"
<command> | predate
se vuoi i millisecondi:
alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"
ma tieni presente che su OSX date non ti offre l'opzione %N, quindi dovrai installare gdate (brew install coreutils
) e così finalmente arriviamo a questo:
alias predate="xargs -I{} sh -c 'gdate +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"
Se il valore che stai anteponendo è lo stesso su ogni riga, avvia emacs con il file, quindi:
Ctrl + <spazio>
all'inizio del file (per contrassegnare quel punto), quindi scorrere 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 riga) e:
Ctrl + X R T
Qual è il comando da inserire nel rettangolo appena specificato (un rettangolo di larghezza 0).
21/8/2008 18:45 <invio>
O qualunque cosa tu voglia anteporre...quindi vedrai quel testo anteposto a ogni riga all'interno del rettangolo di larghezza 0.
AGGIORNAMENTO:Ho appena realizzato che non vuoi la STESSA data, 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 è piuttosto interessante da conoscere...