Почему «... | Sed 'S / ^ / stdout: /' print на пустой stdin, когда `... >> (sed 's / ^ / stdout: /')` нет?

Вам нужен инструмент автоматизации сборки , из которых существует множество . Даже если вы ограничитесь достойными инструментами для создания программ на C ++, которые работают как в Solaris, так и в Windows, вероятно, есть сотни вариантов. Классическим независимым от языка средством автоматизации сборки в мире Unix и Windows является make .Существует общее мнение, что можно добиться большего, но нет единого мнения о том, кто на самом деле добился большего.

Инструменты автоматизации сборки просто выполняют серию инструкций для создания результирующих двоичных файлов и других продуктов из исходного кода. Похоже, вам, вероятно, нужен инструмент непрерывной интеграции , который мог бы делать такие вещи, как извлечение из svn (возможно, автоматически в ловушке фиксации), вызов make, вызов тестовых скриптов, загрузку полученного продукта и результат теста куда-нибудь , отправьте уведомление, когда сборка будет завершена, и покажите какую-то панель с историей сборок.

Не существует де-факто стандартного инструмента непрерывной интеграции, не говоря уже о «лучшем». Просмотрите список Википедии, выберите несколько наиболее подходящих и потратьте несколько минут на просмотр их документации. Затем выберите один и настройте его. Если у вас нет других требований, о которых вы не упомянули, большинство из этих продуктов должно подойти.

3
18.01.2019, 22:32
4 ответа

Ваша первая команда,

( echo foo >&2 ) 2> >(sed 's/^/stderr: /') | sed 's/^/stdout: /'

в упрощенной форме (использование временного файла для хранения данных, созданныхecho):

{ echo foo 2>file >&2; sed 's/^/stderr: /' file; } | sed 's/^/stdout: /'

То есть первый sedсчитывает то, что выдается при стандартной ошибке, из echoи записывает в стандартный вывод, а второй sedчитает и модифицирует это.

Ваша вторая команда,

( echo foo >&2 ) 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')

в упрощенной форме,

echo foo 2>file >&2; sed 's/^/stderr: /' file; sed 's/^/stdout: /' </dev/null

Здесь sed, который получает стандартный вывод ошибки, производит вывод, в то время как другой sed, который получает стандартный вывод, (который ничего не дает ), не производит никакого вывода (, поскольку он не t не получает никаких входных данных, и поскольку он не вставлял и не добавлял никаких данных ).

Другой способ формулировки:

Первая команда:

( echo foo >&2 ) 2>file
sed 's/^/stderr: /' file | sed 's/^/stdout: /'

Вторая команда:

( echo foo >&2 ) 2>file >otherfile
sed 's/^/stderr: /' file
sed 's/^/stdout: /' otherfile

Короче говоря, второй sedво второй команде никогда ничего не читает. В частности, он не считывает вывод первой команды sed, как в первой команде.


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

utility-writing-to-stderr 2> >(something1) | something2

где something1пишет в стандартный вывод, который считывается something2.

Вторая команда, использующая те же обозначения,

utility-writing-to-stderr 2> >(something1) >(something2)

т.е. something1и something2даже не связаны друг с другом, и something2никак не может прочесть, что something1производит. Кроме того, поскольку utility-writing-to-stderrничего не производит в своем стандартном потоке вывода, something2не будет ничего читать из своего стандартного ввода.

3
27.01.2020, 21:15

>работает с ( echo foo >&2 ), а |работает с >(sed 's/^/stderr: /')из-за порядка перенаправления в оболочках. НАПРИМЕР.

$ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /' > >(sed 's/^/stdout: /') )
stdout: stderr: foo

или

$ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') | cat > >(sed 's/^/stdout: /')
stdout: stderr: foo

vs явные примеры порядок в вопросе

$ ( ( echo foo >&2 ) > >(sed 's/^/stdout: /') ) 2> >(sed 's/^/stderr: /')
stderr: foo

или

$ ( ( echo foo >&2 )  | sed 's/^/stdout: /' ) 2> >(sed 's/^/stderr: /')
stderr: foo
1
27.01.2020, 21:15

Эти две команды не эквивалентны.

Команда (1):

( one ) 2> >(two) | three 

Отправляет вывод (std )из twoвthree(Подробнее о stderr ниже ).

Команда (2):

( one ) 2> >(two) > >(three)

Отправляет вывод (std )из oneвthree(stderr переходит вtwo).


Болезненная деталь:

Команда 1:( one ) 2> >(two) | three

  • Команда threeзапущена(sed 's/^/stdout: /')в ожидании ввода на стандартный ввод.
  • Происходит перенаправление2(stderr)на stdinиз two.
  • Происходит внутреннее перенаправление one(echo foo >&2).
  • Команда выполняется, отправляя fooнаstderr(ничего на стандартный вывод ).
  • Слово fooперенаправляется с(stderrизone)на(stdinиз two).
  • Выполняется команда в два(sed 's/^/stderr: /')
  • Теперь измененный выводtwo(stderr: foo)отправляется на стандартный вывод two.
  • Текущий стандартный вывод twoпроходит по каналу к three.
  • Команда three, которая ожидала ввода с самого начала, получает вывод.
  • Вывод изменяется с добавлением ведущего stdout:.
  • Последняя строка stdout: stderr: fooотправляется на tty.

Команда 2:(один )2> > (два )> > (три)

  • Последнее перенаправление(>)создается первым.
  • Команда threeзапускается в ожидании ввода наstdinтолько(>()).
  • Команда threeполучает только стандартный вывод из one.
  • Команда twoзапускается в ожидании ввода.
  • Команда twoполучает(только)стандартный вывод one.
  • Внутреннее перенаправление one соединяет стандартный вывод oneс его stderr.
  • Команда oneвыполняется, отправляя fooнаstderr(изone).
  • fooпереходит вtwo
  • twoизменяет полученную строку на stderr: fooи отправляет ее на tty .
  • threeполучает пустой ввод из стандартного вывода one.
  • threeничего не печатает (, так как нет строки для обработки ).

Поймите, что эта команда:

printf '' | sed 's/^/initial: /'

не имеет вывода (и нет способа заставить его работать ).


Изменение порядка :Команда 3:(один )> > (три )2> > (два)

Направляет вывод twoна three(, а не на деталь tty), оставленную в качестве упражнения.

1
27.01.2020, 21:15

Я проголосовал за очень четкий -урезанный ответ @Kusalananda, но осмелюсь (с опозданием )добавить это к его ответу, как небольшую иллюстрацию замены процессов в действии:

Ваше второе предложение будет работать с небольшим типографским изменением (и сравнительно большим изменением его ошибочной логики):

  $ ( echo foo >&2 ) 2> >(sed 's/^/stderr: /') > >(sed 's/^/stdout: /')
  stderr: foo    # for the well explained reason above

Но:

    v                                          vv
  $ ( (echo foo >&2) 2> >(sed 's/^/stderr: /') )> >(sed 's/^/stdout: /')  
  stdout: stderr: foo

Поскольку добавление ( )>, как показано на рисунке (или >( ), оба работают нормально, )на самом деле позволяет вам создать файл с помощью подстановки процесса, чьи выходные данные могут быть перенаправлены в качестве входных на >(sed 's/^/stdout: /').

Я подумал о том, чтобы добавить это, чтобы проиллюстрировать, как подстановка процесса может быть встроена в подстановку другого процесса. Для удобочитаемости я бы не продвигал его к большему количеству уровней встраивания. Но если по какой-либо причине вам нужно избежать трубы и связанной с ней оболочки , это хорошее решение.

0
27.01.2020, 21:15

Теги

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