2012-01-17 2 views
4

Они работают отлично и делать то, что они должны (напечатать содержимое файла обув):Баш/ЗШ замена входной процесс дает синтаксическую ошибку в сочетании с пока

cat <foo 
while read line; do echo $line; done <foo 
cat <(cat foo) 

Однако это дает мне ошибку синтаксиса в Zsh :

zsh$ while read line; do echo $line; done <(cat foo) 
zsh: parse error near `<(cat foo)' 

и Баш:

bash$ while read line; do echo $line; done <(cat foo) 
bash: syntax error near unexpected token `<(cat foo)' 

кто-нибудь знает причину и, возможно, обходной путь?

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

cat foo | while read line; do echo $line; done 

ответ

6

Вам нужно перенаправить замену процесса в то время цикла:

Вы писали

while read line; do echo $line; done <(cat foo) 

Вам нужно

while read line; do echo $line; done < <(cat foo) 
# ...................................^ 

Лечить замену процесса, как имя файла.

+0

Да, точно. Я понял это за минуту до твоего поста и ответил сам себе :) Но вместо этого я удалю свой ответ и приму твое. Благодаря! –

+0

Отлично! Поэтому 'cat <<(cat foo)' также работает! – olibre

2

я могу предложить только временное решение так:

theproc() { for((i=0;i<5;++i)) do echo $i; } 

while read line ; do echo $line ; done <<<"$(theproc)" 
+0

Нет, извините, это совсем не так. Я даже не уверен, что «eval $ (cat)» должен делать. Он просто блокирует и ждет ввода. –

+0

О, и <(foo) - это замена процесса. Он создаст временный именованный канал, выполнит процесс foo с его stdout, перенаправленным в именованный канал, а затем выполнит материал перед <() с его stdin, перенаправленным на именованный канал. См. Man-страницы bash и zsh для деталей. –

+0

Да, я определенно неправильно вас понял, но с тех пор я обновил ответ :) –

4

bash/zsh заменяет <(cat foo) трубой (вид файла), имеющей имя /dev/fd/n, где n - это дескриптор файла (номер).

Вы можете проверить название трубы, используя команду echo <(cat foo).

Как вы знаете, bash/zsh также выполняет команду cat foo в другом процессе. Вывод этого второго процесса записывается в этот именованный канал.

без процесса замещения:

while ... do ... done inputfile #error 
while ... do ... done < inputfile #correct 

же правил с использованием процесса замещения:

while ... do ... done <(cat foo) #error 
while ... do ... done < <(cat foo) #correct 

Альтернатива:

cat foo >3 & while read line; do echo $line; done <3; 
+0

Интересно! У вас есть источник для этого или вы знаете причину, пока это не поддерживает? Я не нашел это в manpage. В вашем обходном пути будет выполняться цикл while в подоболочке, который вызывает проблемы в моем реальном скрипте. Любая идея, как это можно изменить, чтобы цикл while работал в основной оболочке? –