Command to prepend string to each line?

Solution 1:

Try this:

cmd | awk '{print "[ERROR] " $0}'

Cheers

Solution 2:

cmd | while read line; do echo "[ERROR] $line"; done

has the advantage of only using bash builtins so fewer processes will be created/destroyed so it should be a touch faster than awk or sed.

@tzrik points out that it might also make a nice bash function. Defining it like:

function prepend() { while read line; do echo "${1}${line}"; done; }

would allow it to be used like:

cmd | prepend "[ERROR] "

Solution 3:

With all due credit to @grawity, I'm submitting his comment as an answer, as it seems the best answer here to me.

sed 's/^/[ERROR] /' cmd

Solution 4:

I created a GitHub repository to do some speed tests.

The result is:

  • In the general case, awk is fastest. sed is a bit slower and perl is not much slower than sed. Apparently, all those are highly optimized languages for text processing.
  • In very special situations, where forks dominate, running your script as a compiled ksh script (shcomp) can save even more processing time. In contrast, bash is dead slow compared to compiled ksh scripts.
  • Creating a statically linked binary to beat awk seems not be worth the effort.

In contrast python is dead slow, but I have not tested a compiled case, because it is usually not what you would do in such a scripting case.

Following variants are tested:

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] $_"'

Two binary variants of one of my tools (it is not optimzed for speed, though):

./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''

Python buffered:

python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'

And Python unbuffered:

python -uSc 'import sys
while 1:
 line = sys.stdin.readline()
 if not line: break
 print "[TEST]",line,'

Solution 5:

cmd | sed 's/.*/[ERROR] &/'

Tags:

Shell