Metti un testo davanti a ogni nuova riga che un programma stampa su stdout


9

Quindi voglio fare un po 'di registrazione e quindi mettere una data davanti all'output di uno script bash. Il problema è che ha più righe di output. Sono in grado di mettere solo la data prima dell'intero output. Ma poi ho una riga senza una data nei registri. Ovviamente posso presumere che la data dalla riga sopra sia la stessa, ma speravo che ci fosse una soluzione. Grazie in anticipo!

Questa è la mia sceneggiatura che chiama un'altra sceneggiatura:

#!/bin/sh
echo $(date "+%F %T") : starting script
echo $(date "+%F %T") : $(./script.sh)
echo $(date "+%F %T") :script ended

Questo è l'output:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
second line of output
2012-07-26 15:35:17 : script ended

Ed è quello che vorrei avere:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
2012-07-26 15:35:15 : second line of output
2012-07-26 15:35:17 : script ended

Suppongo che potresti semplicemente cambiare la seconda sceneggiatura?
jmetz,

No, purtroppo no. Ecco perché sono venuto qui.
Tzippy,

Risposte:


9

Secondo una domanda simile su Stack Overflow , ci sono 2 grandi opzioni.

awk ( risposta )

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

annota ( risposta )

annotate è un piccolo script bash, che può essere ottenuto direttamente tramite il link fornito qui, o, su sistemi basati su Debian, attraverso il pacchetto devscripts(sotto forma di annotate-output).



2

Puoi usare awk

./script.sh | awk '{ print d,$1}' "d=$(date "+%F %T")"

awkprende un flusso di input e modifica il suo output. Questo script dice "stampa d seguito dall'output originale", quindi popola dcon la data.


1
Questo non valuta anche l' dateespressione una sola volta, in modo che tutte queste righe vengano stampate allo stesso tempo?
Daniel Beck

@DanielBeck Sì, sì, avevo supposto che stesse rilevando la data ogni volta, ma avevo appena finito il mio test abbastanza rapidamente
Paul,

1

Questo stamperà la data e l'ora correnti prima di ogni riga di output di ./script.sh:

set -f
./script.sh | while read -r LINE; do echo $(date "+%F %T") : "$LINE"; done
set +f

Come funziona

  • set -fdisattiva l'espansione bash (o echo *non stampa un vero asterisco).

  • while read -r LINE; do ... donesalva una riga di output nella variabile $LINEed esegue ..., fino a quando tutte le righe non vengono elaborate.

  • echo $ (data "+% F% T"): "$ LINE" stampa la riga con l'ora e la data correnti.

  • set +f riattiva l'espansione bash, quindi non interferirà con il resto del tuo script bash.


Viene valutato una sola volta, quindi ogni sedinserisce la stessa data, appena prima di iniziare il secondo script. Probabilmente non quello che l'utente vuole ...
Daniel Beck

Non penso che neanche questo tentativo funzionerà. AFAIK, l'intera subshell viene valutata per prima, quindi il ciclo viene attraversato. Quindi ora i tempi sono trascorsi dopo l'esecuzione.
Daniel Beck

Il tuo esempio non funziona, poiché ritardi solo l'output, non l'esecuzione di ls. Prova la tua sceneggiatura con quanto segue script.sh: #!/bin/bash(newline)echo 1 ; sleep 1 ; echo 2 ; sleep 2 ; echo 3 ; sleep 3 ; echo 4
Daniel Beck

Utilizzare readcon un whileciclo anziché un ciclo for.
Chepner,

@chepner: buona idea.
Dennis,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.