Еще вопросы о копрокате - PullRequest
4 голосов
/ 07 октября 2011

Это продолжение bash coproc и оставшегося вывода coproc

Идиома, на которой я окончательно остановился для обработки файла по одной строке за раз:

coproc cat auto/etc/build.cfg
while read -u ${COPROC[0]} BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS
do
    ... commands ...
done

Я знаю для простого случая cat Я мог бы просто использовать перенаправление ввода.Это упрощенная версия, где реальная использует egrep для выбора подмножества строк.

К сожалению, это не работает.

$ cat test.sh
coproc cat auto/etc/build.cfg
while read -u ${COPROC[0]} BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS
do
    echo hello
done

$ bash -x test.sh
+ read -u 63 BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS
+ cat auto/etc/build.cfg
+ echo hello
hello
+ read -u BRANCH TARGET SVNSRC SVNTAG BUILDTYPE DISTTYPE DISTARGS
test.sh: line 2: read: BRANCH: invalid file descriptor specification

Похоже, что хотя есть 4 строкив файле ко времени второй итерации сопроцесс исчез вместе со своими файловыми дескрипторами, а переменная ${COPROC[*]} стала неустановленной (обратите внимание на отсутствие fd во втором чтении).

Чтобы усложнитьимеет значение, я работаю как в Cygwin, так и в Linux (Fedora), и это демонстрирует немного различное поведение в двух средах.В Linux я получаю поведение, описанное выше.В Cygwin некоторые команды (например, echo, являющиеся встроенными в bash) не вызывают этой проблемы.В обеих средах выполнение любой внешней команды убивает сопроцесс и отбрасывает его дескрипторы.

Я предполагаю, что реальный вопрос здесь такой:

В bash, как мне выполнить

while read (list of vars) from file
do
    one or more commands
done

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

Я действительно удивлен, что это так сложно в bash.

Ответы [ 2 ]

5 голосов
/ 07 октября 2011

Я не уверен, почему ваше использование coproc не работает.Ваш пример работает для меня с bash 4.2.8 на Mac OS X. Возможно, некоторые версии bash содержат ошибки.

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

while read foo bar baz quux; do
    : use foo, bar, baz, quux in various commands
done < <(commands | that | generate --your lines-to-read)

Это может быть удобно, когда ваш ввод еще не находится в простом файле, где вы можете использовать простое перенаправление.чтобы придерживаться coproc, вы можете использовать альтернативную формулировку:

coproc { commands | that | generate --your lines-to-read ; }
while read foo bar baz quux; do
    : use foo, bar, baz, quux in various commands
done <&${COPROC[0]}
2 голосов
/ 07 октября 2011

Один из синтаксисов этого:

while read var1 var2 ... ; do
   # one or more commands
done < file
...