Как префикс любого вывода в скрипте bash?

Решение в TXR Lisp:

(let* ((data [mapcar file-get-lines (glob "file*")]))
  (mapdo (op file-put-lines `out@2` @1) (transpose data) (range 1)))

Выполнить:

$ ls
file0  file1  trans.tl
$ txr trans.tl
$ ls
file0  file1  out1  out2  out3  trans.tl
$ cat out1
000 010 020 030
001 011 021 031
$ cat out2
100 110 120 130
101 111 121 131
$ cat out3
200 210 220 230
201 211 221 231

18
27.04.2018, 16:33
2 ответа

Вы можете перенаправить stderr/stdout на подстановку процесса, которая добавляет выбранный префикс. Например, этот скрипт:

#! /bin/bash
exec > >(trap "" INT TERM; sed 's/^/foo: /')
exec 2> >(trap "" INT TERM; sed 's/^/foo: (stderr) /' >&2)
echo foo
echo bar >&2
date

Производит этот вывод:

foo: foo
foo: (stderr) bar
foo: Fri Apr 27 20:04:34 IST 2018

Первые две строки перенаправляют stdout и stderr соответственно на команды sed, которые добавляют foo: и foo: (stderr)к входным данным.
Вызовы встроенной оболочки -в команде trapгарантируют, что подоболочка не завершится при завершении сценария с помощью Ctrl+Cили при отправке сигнала SIGTERMс помощью kill $pid. Это гарантирует, что ваша оболочка не завершит ваш скрипт принудительно, потому что файловый дескриптор stdoutисчезает при завершении sed, потому что он также получил сигнал завершения. По сути, вы по-прежнему можете использовать ловушки выхода в своем основном скрипте, и sedпо-прежнему будет работать для обработки любых выходных данных, сгенерированных при запуске ваших ловушек выхода. Подоболочка все еще должна завершиться после завершения вашего основного скрипта, чтобы процесс sedне оставался запущенным навсегда.

44
27.01.2020, 19:45

Один из вариантов в bash — сделать это путем перенаправления на процесс замены, что-то вроде этого:

./script.sh > >(sed 's/^/script: /') 2> >(sed 's/^/script (err): /' >&2)

Проблема в том, что вывод может быть не в порядке (, как упоминал Чарльз Даффи в комментарии ). Это также действительно раздражающе громоздко. Но вы можете сделать для него функцию-оболочку:

prefixwith() {
    local prefix="$1"
    shift
    "$@" > >(sed "s/^/$prefix: /") 2> >(sed "s/^/$prefix (err): /" >&2)
}
prefixwith "From script"./script.sh

Или сделать это еще проще, используя имя команды в качестве префикса:

prefixoutput() {
    local prefix="From ${1##*/}"
    "$@" > >(sed "s/^/$prefix: /") 2> >(sed "s/^/$prefix (err): /" >&2)
}
prefixoutput./script.sh
4
27.01.2020, 19:45

Теги

Похожие вопросы