Ответы:
cmd | while read line; do echo "[ERROR] $line"; done
имеет преимущество только использования встроенных команд bash, так что будет создаваться / уничтожаться меньше процессов, поэтому он должен быть на ощупь быстрее, чем awk или sed.
@tzrik указывает, что это может также сделать хорошую функцию bash. Определяя это как:
function prepend() { while read line; do echo "${1}${line}"; done; }
позволит использовать его как:
cmd | prepend "[ERROR] "
sed) или даже разбиение строк ( awk).)
function prepend() { while read line; do echo "${1}${line}"; done; }
Попробуй это:
cmd | awk '{print "[ERROR] " $0}'
ура
awk -vT="[ERROR] " '{ print T $0 }'илиawk -vT="[ERROR]" '{ print T " " $0 }'
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'илиT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
cmd | awk '{print "['$V]' " $0}'- это должно быть оценено один раз в начале, так что никаких потерь производительности не будет.
С уважением к @grawity, я представляю его комментарий в качестве ответа, так как он кажется мне лучшим ответом.
sed 's/^/[ERROR] /' cmd
awkОдин-лайнер достаточно хорош, но я думаю , что все больше людей знакомы с sedчем awk. Сценарий bash хорош для того, что он делает, но кажется, что он отвечает на вопрос, который не был задан.
sed X cmdчитает cmdи не выполняет его. Либо cmd | sed 's/^/[ERROR] /'или, sed 's/^/[ERROR] /' <(cmd)либо cmd > >(sed 's/^/[ERROR] /'). Но остерегайтесь последнего. Даже то , что это позволяет получить доступ к возвращаемому значению cmdв sedпрогонах в фоновом режиме, так что, скорее всего , вы увидите результат после ЦМДА готового. Хорошо для входа в файл, хотя. И обратите внимание, что, awkвероятно, быстрее, чем sed.
alias lpad="sed 's/^/ /'", вместо ОШИБКИ я вставляю 4 пробела. Теперь для магического трюка: ls | lpad | pbcopyперед выводом ls будет добавлено 4 пробела, которые помечают его как Markdown для кода , что означает, что вы вставляете буфер обмена ( pbcopy захватывает его на macs) непосредственно в StackOverflow или любой другой контекст уценки. Не удалось получить ответ aliasот awk (с 1-й попытки), поэтому этот выигрывает. Решение while read также может создавать псевдонимы, но я нахожу это sed более выразительным.
Я создал GitHub-репозиторий для тестирования скорости.
Результат:
awkсамый быстрый. sedнемного медленнее и perlне намного медленнее, чем sed. По-видимому, все это высоко оптимизированные языки для обработки текста.kshскрипта ( shcomp) может сэкономить еще больше времени на обработку. Напротив, он bashочень медленный по сравнению со скомпилированными kshскриптами.awkКажется, создание статически связанного двоичного файла не стоит этих усилий.Напротив, он pythonочень медленный, но я не проверял скомпилированный случай, потому что это обычно не то, что вы бы сделали в таком случае сценариев.
Тестируются следующие варианты:
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] $_"'
Два бинарных варианта одного из моих инструментов (хотя он не оптимизирован по скорости):
./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''
Python буферизован:
python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'
И Python небуферизованный:
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 }'вывести метку времени
Я хотел решение, которое обрабатывало бы stdout и stderr, поэтому я написал prepend.shи поставил его на моем пути:
#!/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)
Теперь я могу просто запустить prepend.sh "[ERROR]" cmd ..., чтобы добавить «[ERROR]» к выводу cmd, и при этом разделить stderr и stdout.
>(оболочками происходило что-то, что я не мог решить. Казалось, что сценарий завершается, и вывод возвращается на терминал после возвращения приглашения, что было немного грязно. В конце концов я пришел с ответом здесь stackoverflow.com/a/25948606/409638