Risposte:
cmd | while read line; do echo "[ERROR] $line"; done
ha il vantaggio di usare solo i built-in bash in modo che vengano creati / distrutti meno processi, quindi dovrebbe essere un tocco più veloce di awk o sed.
@tzrik sottolinea che potrebbe anche fare una bella funzione bash. Definendolo come:
function prepend() { while read line; do echo "${1}${line}"; done; }
gli permetterebbe di essere usato come:
cmd | prepend "[ERROR] "
sedawk
function prepend() { while read line; do echo "${1}${line}"; done; }
Prova questo:
cmd | awk '{print "[ERROR] " $0}'
Saluti
awk -vT="[ERROR] " '{ print T $0 }'oppureawk -vT="[ERROR]" '{ print T " " $0 }'
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'oppureT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
cmd | awk '{print "['$V]' " $0}'- questo dovrebbe essere valutato una volta all'inizio, quindi nessun sovraccarico di prestazioni.
Con tutto il merito di @grawity, sto inviando il suo commento come risposta, in quanto mi sembra la risposta migliore qui.
sed 's/^/[ERROR] /' cmd
awkL'one-liner è abbastanza bello, ma penso che più persone hanno familiarità con sedrispetto awk. Lo script bash è buono per quello che fa, ma sembra che stia rispondendo a una domanda che non è stata posta.
sed X cmdlegge cmde non lo esegue. O cmd | sed 's/^/[ERROR] /'oppure sed 's/^/[ERROR] /' <(cmd)oppure cmd > >(sed 's/^/[ERROR] /'). Ma attenzione a quest'ultimo. Anche che questo ti permette di accedere il valore di ritorno cmdle sedcorse in background, quindi è probabile che si vede l'uscita dopo cmd finiti. Buono per l'accesso a un file, però. E nota che awkprobabilmente è più veloce di sed.
alias lpad="sed 's/^/ /'". invece di ERRORE inserisco 4 spazi iniziali. Ora, per il trucco magico: ls | lpad | pbcopyanteporrà l'output con 4 spazi che lo contrassegnano come Markdown per il codice , il che significa che si incolla gli appunti ( pbcopy lo prende, su Mac) direttamente in StackOverflow o in qualsiasi altro contesto markdown. Non è stata aliasla risposta awk (al primo tentativo), quindi questo vince. Anche la soluzione while read è alias, ma trovo questa sed più espressiva.
Ho creato un repository GitHub per eseguire alcuni test di velocità.
Il risultato è:
awkè il più veloce. sedè un po 'più lento e perlnon è molto più lento di sed. Apparentemente, tutti questi sono linguaggi altamente ottimizzati per l'elaborazione del testo.kshscript compilato ( shcomp) può risparmiare ancora più tempo di elaborazione. Al contrario, bashè molto lento rispetto agli kshscript compilati .awknon sembra valere la pena.Al contrario pythonè molto lento, ma non ho testato un caso compilato, perché di solito non è quello che faresti in un caso di scripting.
Vengono testate le seguenti varianti:
while read line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST]" $line; done
while read -r line; do echo "[TEST]" "$line"; done
sed 's/^/[TEST] /'
awk '{ print "[TEST] " $0 }'
awk -vT="[TEST] " '{ print T $0 }'
awk -vT="[TEST]" '{ print T " " $0 }'
awk -vT="[TEST]" 'BEGIN { T=T " "; } { print T $0 }'
T="[TEST] " awk '{ print ENVIRON["T"] $0 }'
T="[TEST]" awk '{ print ENVIRON["T"] " " $0 }'
T="[TEST]" awk 'BEGIN { T=ENVIRON["T"] " " } { print T $0 }'
perl -ne 'print "[TEST] $_"'
Due varianti binarie di uno dei miei strumenti (non è ottimizzato per la velocità, però):
./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''
Python bufferato:
python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'
E Python senza buffer:
python -uSc 'import sys
while 1:
line = sys.stdin.readline()
if not line: break
print "[TEST]",line,'
awk -v T="[TEST %Y%m%d-%H%M%S] " '{ print strftime(T) $0 }'per emettere un timestamp
Volevo una soluzione che gestisse stdout e stderr, quindi l'ho scritta prepend.she inserita nel mio percorso:
#!/bin/bash
prepend_lines(){
local prepended=$1
while read line; do
echo "$prepended" "$line"
done
}
tag=$1
shift
"$@" > >(prepend_lines "$tag") 2> >(prepend_lines "$tag" 1>&2)
Ora posso solo eseguire prepend.sh "[ERROR]" cmd ..., anteporre "[ERROR]" all'output di cmd, e avere comunque stderr e stdout separati.
>(subshells che non riuscivo a risolvere del tutto. Sembrava che lo script fosse completato e l'output stava arrivando al terminale dopo che il prompt era tornato, il che era un po 'disordinato. Alla fine ho trovato la risposta qui stackoverflow.com/a/25948606/409638