Buscando algo como esto? ¿Algunas ideas?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Buscando algo como esto? ¿Algunas ideas?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Respuestas:
cmd | while read line; do echo "[ERROR] $line"; done
tiene la ventaja de usar solo bash builtins, por lo que se crearán / destruirán menos procesos, por lo que debería ser un toque más rápido que awk o sed.
@tzrik señala que también podría ser una buena función bash. Definiéndolo como:
function prepend() { while read line; do echo "${1}${line}"; done; }
permitiría que se use como:
cmd | prepend "[ERROR] "
sed) o incluso división de cadenas ( awk).)
function prepend() { while read line; do echo "${1}${line}"; done; }
Prueba esto:
cmd | awk '{print "[ERROR] " $0}'
Aclamaciones
awk -vT="[ERROR] " '{ print T $0 }'oawk -vT="[ERROR]" '{ print T " " $0 }'
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'oT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
cmd | awk '{print "['$V]' " $0}'- esto debe evaluarse una vez al comienzo, para que no haya sobrecarga de rendimiento.
Con todo el crédito debido a @grawity, envío su comentario como respuesta, ya que me parece la mejor respuesta.
sed 's/^/[ERROR] /' cmd
awkone-liner es lo suficientemente agradable, pero creo que hay más personas con las sedque está familiarizado awk. El script bash es bueno para lo que hace, pero parece que está respondiendo una pregunta que no se hizo.
sed X cmdlee cmdy no lo ejecuta. O cmd | sed 's/^/[ERROR] /'o sed 's/^/[ERROR] /' <(cmd)o cmd > >(sed 's/^/[ERROR] /'). Pero cuidado con lo último. Incluso eso le permite acceder al valor de retorno de cmdlas sedejecuciones en segundo plano, por lo que es probable que vea la salida después de que finalice el cmd. Sin embargo, es bueno para iniciar sesión en un archivo. Y tenga en cuenta que awkprobablemente es más rápido que sed.
alias lpad="sed 's/^/ /'". en lugar de ERROR inserto 4 espacios iniciales. Ahora, para el truco de magia: ls | lpad | pbcopyantepondrá la salida ls con 4 espacios que lo marcan como Markdown para el código , lo que significa que pega el portapapeles ( pbcopy lo agarra, en Mac) directamente en StackOverflow o cualquier otro contexto de reducción. No se pudo responder aliasel awk (en el primer intento), así que este gana. La lectura, mientras que la solución es también capaz de alias, pero me parece que esta sed más expresiva.
Creé un repositorio de GitHub para hacer algunas pruebas de velocidad.
El resultado es:
awkes el más rápido. sedes un poco más lento y perlno es mucho más lento que sed. Aparentemente, todos esos son lenguajes altamente optimizados para el procesamiento de texto.kshscript compilado ( shcomp) puede ahorrar aún más tiempo de procesamiento. Por el contrario, bashes muy lento en comparación con los kshscripts compilados .awkno parece valer la pena.Por el contrario, pythones muy lento, pero no he probado un caso compilado, porque generalmente no es lo que haría en un caso de secuencias de comandos.
Se prueban las siguientes variantes:
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] $_"'
Dos variantes binarias de una de mis herramientas (aunque no está optimizada para la velocidad):
./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''
Python tamponado:
python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'
Y Python sin búfer:
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 }'emitir una marca de tiempo
Quería una solución que manejara stdout y stderr, así que escribí prepend.shy la puse en mi camino:
#!/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)
Ahora solo puedo ejecutar prepend.sh "[ERROR]" cmd ..., para anteponer "[ERROR]" a la salida de cmd, y todavía tengo stderr y stdout separados.
>(subcapas que no pude resolver. Parecía que el script se estaba completando, y la salida llegaba a la terminal después de que el aviso había regresado, lo cual era un poco desordenado. Eventualmente se me ocurrió la respuesta aquí stackoverflow.com/a/25948606/409638