2010-09-01 2 views
41

Есть ли способ, в bash, передать трубку stderr через фильтр, прежде чем объединять его с stdout? То есть, я хочутруба только stderr через фильтр

stdout ----------------\ 
         |-----> terminal/file/whatever 
stderr -- [ filter ] --/ 

вместо

stdout ----\ 
      |----[ filter ]---> terminal/file/whatever 
stderr ----/ 
+1

Смотрите также [Как труба STDERR, а не stdou т?] (http://stackoverflow.com/questions/2342826/how-to-pipe-stderr-and-not-stdout). –

ответ

43

Вот пример, по образцу how to swap file descriptors in bash. Вывод a.out следующий, без префикса STDXXX:.

STDERR: stderr output 
STDOUT: more regular 

./a.out 3>&1 1>&2 2>&3 3>&- | sed 's/e/E/g' 
more regular 
stdErr output 

Цитирование из приведенной выше ссылке:

  1. сначала сохранить стандартный вывод, как & 3 (& 1 обманут в 3)
  2. Далее отправить стандартный вывод на стандартный вывод ошибок (& 2 обманут в 1)
  3. Отправить stderr to & 3 (стандартный) (& 3 обманут в 2)
  4. близко & 3 (& - обманут в 3)
+1

Дополнительная информация: [BashFAQ/047] (http://mywiki.wooledge.org/BashFAQ/047) –

+4

Это работает с любой оболочкой POSIX, а не только с Bash. – Rufflewind

+0

Это не работает для меня. Наконец, я работаю с '3> & 2 2> & 1 1> & 3-'. – aleung

5

Последняя часть this page в Advanced Bash Scripting Guide является "перенаправление только STDERR к трубе".

# Перенаправление только stderr в трубу.

exec 3>&1        # Save current "value" of stdout. 
ls -l 2>&1 >&3 3>&- | grep bad 3>&- # Close fd 3 for 'grep' (but not 'ls'). 
#    ^^^^ ^^^^ 
exec 3>&-        # Now close it for the remainder of the script. 

# Спасибо S.C.

Это может быть то, что вы хотите. Если нет, какая-то другая часть ABSG должна помочь вам, это отлично.

+0

Мы несколько нерешительны, чтобы рекомендовать ABSG в качестве справочного материала, поскольку он смешивает документацию, рецепт и мнение без четкой маркировки различий. В некоторых разделах также есть сомнительный контент, хотя тот, с которым вы ссылаетесь, кажется прекрасным. – tripleee

3

Посмотрите на именованные каналы:

$ mkfifo err 
$ cmd1 2>err |cat - err |cmd2 
+0

не будет 'cat - err' сломать вставку stdout и stderr? –

+0

@Martin - все зависит. Если вывод cmd1, cat, ** или ** cmd2 выводится, вы можете увидеть выход из последовательности. – mob

7

Я считаю использование подстановки процессов Баш легче запомнить и использовать, поскольку он отражает первоначальное намерение почти дословно. Например:

$ cat ./p 
echo stdout 
echo stderr >&2 
$ ./p 2> >(sed -e 's/s/S/') | sed 's/t/T/' 
sTdout 
STderr 

использует первую команду SED в качестве фильтра на STDERR только и второй SED команды, чтобы изменить соединенный выход.

Обратите внимание, что пробел после 2> является обязательным для правильной обработки команды.

14

Наивное использование подстановки процессов, кажется, позволяет фильтровать stderr отдельно от stdout:

:; (echo out ; echo err >&2) 2> >(sed s/^/e:/ >&2) 
out 
e:err 

Обратите внимание, что stderr выходит на stderr и stdout на stdout, которые мы можем видеть, завернув все это в другом подоболочка и перенаправлении файлов o и e

((echo out ; echo err >&2) 2> >(sed s/^/e:/ >&2)) 1>o 2>e 
+0

почему:; в начале? Я пробовал магическую линию без, и, похоже, не имеет никакого значения. – Koshmaar

+0

Некоторые люди используют '$' в качестве командной строки. Затем они часто пишут примеры оболочки, например: '$ cat/var/log/syslog | fgrep ... '. Тем не менее, эта строка не доступна для копирования из-за '$'. ':;' выглядит как подсказка, но в основном оболочка no-op; поэтому вы можете безопасно выбирать и вставлять всю строку. – solidsnack

+11

Хорошо, но вы могли бы просто опустить:; и линия была бы также скопированой :) Мне:; не похоже на подсказку, он не делал пример более ясным (отделяя команды от вывода), но запутывая. Хотя я понимаю вашу точку зрения и давайте не будем обсуждать синтаксис/соглашения. – Koshmaar

Смежные вопросы