Объединение канала с состоянием выхода в скрипте bash.

У меня есть команда bash shell-script, которая запускает date, если make завершается успешно (завершается с нулевым статусом выхода) и наоборот:

make && date

но теперь я хочу обработать его вывод, например

make | sed s/a/A/

Если я сделаю

make | sed s/a/A/ && date

дата запускается, даже если make потерпел неудачу

Если я вместо этого

make && date | sed s/a/A/

sed обрабатывает вывод даты вместо make.

Знаете ли вы о каком-либо решении? Спасибо!


PS я пробовал это:

(make | sed s/a/A/) && date

дата по- прежнему работает, когда make не удается.

(make && (date > /dev/null)) | sed s/a/A/

дата не запускается, когда make успешен.

3 ответа

Решение

Если у вас есть оболочка с подстановкой процесса (bash делает, posix shell нет), чем

make > >(sed s/a/A/) && date

должен делать свое дело, за исключением bash, он не ждет sed (кажется, zsh делает, но я только попробовал, но не проверил doc), поэтому выходные данные date могут быть получены до последней строки вывода sed. В простой оболочке posix вы можете использовать немного более сложную конструкцию

((make && date >&3) | sed s/a/A/) 3>&1

Дата может снова запуститься до того, как sed обработает все, поэтому ее вывод может снова прийти до последней строки вывода sed.

Если вы хотите, чтобы дата запускалась только после того, как sed обработал все, ваш единственный шанс - сохранить где-нибудь статус make. Что-то вроде:

(make && touch make-succeeded) | sed s/a/A/
rm make-succeeded 2>/dev/null && date

злоупотребляя тем фактом, что если файл не существует, rm (без -f) выйдет с ненулевым статусом и отключит сообщение об ошибке с перенаправлением. Однако, как уже упоминал Фредрик, в bash действительно есть место, где он сохраняет статус выхода, поэтому в bash вы можете:

make | sed s/a/A/
[ 0 -eq $PIPESTATUS[0] ] && date

Включи pipefail в make подоболочка.

(set -o pipefail; make 2>/dev/null | sed s/a/A/) && date

В основном, как это;

my_make () {
  local rc
  make >tmp
  rc=$?
  sed s/a/A/ tmp
  rm tmp
  return $rc
}

Временный файл, очевидно, должен обрабатываться надлежащим образом; это пустяки, чтобы сосредоточиться на проблеме под рукой. Возможно, вы могли бы вообще избежать временного файла, если вы умны с файловыми дескрипторами, но сейчас пятница, и мне нужно больше кофе.

Другие вопросы по тегам