Ітерація над результатом команди в 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')

Я міг би зберегти вихід цієї команди у тимчасовий файл і використовувати переспрямування на тимчасовий файл, але я хотів уникнути цього.

Отже, чому перенаправлення дає мені помилку, і чи є у мене інші способи, ніж створення тимчасового файлу?


Відповіді:


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
Google "процес заміни". наприклад tldp.org/LDP/abs/html/abs-guide.html#PROCESS-SUB
кендирь

Слід зазначити, що підміна <() використовує дескриптори файлів, а в деяких операційних системах буде прозоро створюватися та використовувати тимчасові файли.
ewindisch

@Zoredache: Просто шукайте <(у посібнику по bash (він знаходиться в розділі "Заміна процесу").
Жил "ТАК - перестань бути злим"

@ewindisch, якщо інструмент прозоро створює темпфіл, що добре, я просто не хотів створювати його вручну, коли я був впевнений, що мені це не потрібно.
Зоредаче

0

Ще кілька альтернатив, якщо хтось знову приїде сюди ...

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

/bin/false || echo "ignoring error"

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.