Ответы:
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