Respostas:
cmd | while read line; do echo "[ERROR] $line"; done
tem a vantagem de usar apenas bash built-in para que menos processos sejam criados / destruídos, portanto deve ser um toque mais rápido que awk ou sed.
O @tzrik ressalta que também pode ser uma boa função do bash. Definindo-o como:
function prepend() { while read line; do echo "${1}${line}"; done; }
permitiria que fosse usado como:
cmd | prepend "[ERROR] "
sed
) ou divisão corda mesmo ( awk
) são utilizados.)
function prepend() { while read line; do echo "${1}${line}"; done; }
Tente o seguinte:
cmd | awk '{print "[ERROR] " $0}'
Felicidades
awk -vT="[ERROR] " '{ print T $0 }'
ouawk -vT="[ERROR]" '{ print T " " $0 }'
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'
ouT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
cmd | awk '{print "['$V]' " $0}'
- isso deve ser avaliado uma vez no início, para que não haja sobrecarga de desempenho.
Com todo o crédito devido a @grawity, estou enviando o comentário dele como resposta, pois parece a melhor resposta aqui para mim.
sed 's/^/[ERROR] /' cmd
awk
one-liner é bom o suficiente, mas eu acho que as pessoas estão mais familiarizados com sed
que awk
. O script bash é bom para o que faz, mas parece que está respondendo a uma pergunta que não foi feita.
sed X cmd
lê cmd
e não o executa. Ou cmd | sed 's/^/[ERROR] /'
ou sed 's/^/[ERROR] /' <(cmd)
ou cmd > >(sed 's/^/[ERROR] /')
. Mas cuidado com o último. Mesmo que este permite que você acesse o valor de retorno cmd
as sed
corridas no fundo, por isso é provável que você veja a saída após cmd acabados. É bom para fazer login em um arquivo. E note que awk
provavelmente é mais rápido que sed
.
alias lpad="sed 's/^/ /'"
. em vez de ERRO, insiro 4 espaços à esquerda. Agora, o truque de mágica: ls | lpad | pbcopy
acrescentará ls à saída com 4 espaços que a marcarão como Markdown para código , o que significa que você cola a área de transferência ( pbcopy agarra-a no macs) diretamente no StackOverflow ou em qualquer outro contexto de marcação. Não foi possível alias
a resposta do awk (na 1ª tentativa), então esta vence. A leitura, enquanto solução é também pseudônimo-capaz, mas eu acho isso sed mais expressivo.
Criei um repositório 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, todos esses são idiomas altamente otimizados para processamento de texto.ksh
script compilado ( shcomp
) pode economizar ainda mais tempo de processamento. Por outro lado, bash
é muito lento comparado aos ksh
scripts compilados .awk
não vale o esforço.Por outro lado, python
é muito lento, mas 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 ''
Buffer em Python:
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,'
awk -v T="[TEST %Y%m%d-%H%M%S] " '{ print strftime(T) $0 }'
para gerar um carimbo de data
Eu queria uma solução que tratasse 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 apenas executar prepend.sh "[ERROR]" cmd ...
, para acrescentar "[ERROR]" à saída de cmd
e ainda ter stderr e stdout separados.
>(
subshells que eu não conseguia resolver. Parecia que o script estava sendo concluído e a saída estava chegando ao terminal depois que o prompt retornou, o que foi um pouco confuso. Eu finalmente veio com a resposta aqui stackoverflow.com/a/25948606/409638