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