Назад | Перейти на главную страницу

Команда для добавления строки к каждой строке?

Ищете что-то подобное? Любые идеи?

cmd | prepend "[ERRORS] "

[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc

Попробуй это:

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

Ура

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] "

При всем уважении к @grawity, я отправляю его комментарий в качестве ответа, так как он кажется мне лучшим ответом здесь.

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

Я создал Репозиторий 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,'
cmd | sed 's/.*/[ERROR] &/'

Мне нужно было решение, обрабатывающее 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.

cmd | xargs -L 1 -i echo "prefix{}"

или даже проще в случае prefix отделяется от самой строки пробелами

cmd | xargs -L 1 echo prefix

Это не очень эффективно с точки зрения производительности, но краткое описание.

Он работает, запустив echo один раз на каждую строку ввода. xargs позволяет также обрабатывать \0-ограниченные строки.