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

È stato utile?

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

http://expect.nist.gov

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top