Еще вопросы о копрокате

Это продолжение 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 ответа

Решение

Я не уверен, почему вы используете 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]}

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

while read var1 var2 ... ; do
   # one or more commands
done < file
Другие вопросы по тегам