Перебрать вывод команды в bash без вложенной оболочки

9

Я хочу перебрать вывод команды без создания вложенной оболочки или использования временного файла.

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

sysctl -a 2>/dev/null | grep '\.rp_filter' | while read -r -a RPSTAT ; do

  if [[ "0" != "${RPSTAT[2]}" ]] ; then
    echo >&2 "RP Filter must be disabled on all interfaces!"
    echo >&2 "The RP filter feature is incompatible with policy routing"
    exit 1
  fi
done

Поэтому одна из предложенных альтернатив - использовать такую ​​команду, чтобы избежать подоболочки.

while read BLAH ; do echo $BLAH; done </root/regularfile

Поэтому мне кажется, что я также должен иметь возможность использовать такую ​​команду, чтобы избежать подоболочки и при этом получить результат от программы, которую я хочу.

while read BLAH ; do echo $BLAH; done <(sysctl -a 2>/dev/null | grep '\.rp_filter')

К сожалению, использование этой команды приводит к этой ошибке.

-bash: syntax error near unexpected token `<(sysct ...

Я действительно запутался, так как это работает.

cat <(sysctl -a 2>/dev/null | grep '\.rp_filter')

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

Так почему же перенаправление дает мне ошибку, и у меня есть какие-либо варианты, кроме создания временного файла?

Zoredache
источник

Ответы:

13

Вы пропустили <. Должно быть:

while read BLAH ; do echo $BLAH; done < <(sysctl -a 2>/dev/null | grep '\.rp_filter')

Думайте о <(sysctl -a 2>/dev/null | grep '\.rp_filter')том, чтобы быть файлом.

кендырь
источник
Большое спасибо. Просто для моего назидания, можете ли вы указать мне на справочную страницу, справку или веб-страницу, которая документирует это? Я не мог заставить Google указать мне на что-нибудь полезное, пытаясь найти это.
Зоредаче
2
Гугл "процесс замещения". например, tldp.org/LDP/abs/html/abs-guide.html#PROCESS-SUB
собачья баня
Следует отметить, что подстановка <() использует файловые дескрипторы и в некоторых операционных системах прозрачно создает и использует временные файлы.
ewindisch
@Zoredache: просто найдите <(в руководстве по bash (оно находится в разделе «процесс подстановки»).
Жиль "ТАК - перестань быть злым"
@ewindisch, если инструмент прозрачно создает временный файл, что нормально, я просто не хотел создавать его вручную, когда был уверен, что мне это не нужно.
Zoredache
0

Еще несколько вариантов, если кто-нибудь придет сюда снова ...

В зависимости от оболочки, вы можете использовать set -o errexitродительскую оболочку для выхода, когда команда (включая подоболочку) завершает работу с ненулевым значением, не будучи пойманным в ifблоке или в конце &&или ||, как в

/bin/false || echo "ignoring error"

Или вы могли бы использовать подоболочку, чтобы сообщить родителю, используя kill и переменную среды $ PPID, если она доступна.

Или вы можете переместить блок while в функцию и вернуть 0/1 (явно возвращать 0 после блока while) и просто сделать свой конвейер как sysctl | grep | function || exit. Я полагаю, вы могли бы также поместить возвраты во встроенный блок, но функции - ваш друг. ;)

dannysauer
источник