cmd | while read line; do echo "[ERROR] $line"; done
tem a vantagem de usar somente o built-in bash para que menos processos sejam criados / destruídos, então deve ser mais rápido que o awk ou o sed
.Procurando por algo assim? Alguma idéia?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Tente isto:
cmd | awk '{print "[ERROR] " $0}'
Felicidades
Com todo o crédito devido a @grawity, estou enviando o comentário dele como resposta, já que parece a melhor resposta aqui para mim.
sed 's/^/[ERROR] /' cmd
Eu criei um repositório do GitHub para fazer alguns testes de velocidade.
O resultado é:
awk
é o mais rápido. sed
é um pouco mais lento e perl
não é muito mais lento que sed
. Aparentemente, todas essas linguagens são altamente otimizadas para processamento de texto. ksh
compilado ( shcomp
) pode economizar ainda mais tempo de processamento. Por outro lado, bash
é muito lento comparado aos scripts ksh
compilados. awk
parece não valer o esforço. Em contraste, python
é muito lento, mas eu não testei um caso compilado, porque geralmente não é o que você faria em um caso de script.
As seguintes variantes são testadas:
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] $_"'
Duas variantes binárias de uma das minhas ferramentas (embora não seja otimizada para velocidade):
./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''
Python em buffer:
python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'
E Python sem buffer:
python -uSc 'import sys
while 1:
line = sys.stdin.readline()
if not line: break
print "[TEST]",line,'
cmd | sed 's/.*/[ERROR] &/'
Eu queria uma solução que lidasse com stdout e stderr, então escrevi prepend.sh
e coloquei no meu caminho:
#!/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)
Agora, posso executar apenas prepend.sh "[ERROR]" cmd ...
para preceder "[ERROR]" na saída de cmd
e ainda ter stderr e stdout separados.