Решение в 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
Вы можете перенаправить 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
не оставался запущенным навсегда.
Один из вариантов в 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