2014-11-13 4 views
1

Я пытаюсь перебрать вывод процесса Perl по строкам в пределах цикла while. Однако я испытываю трудности с синтаксисом.вывод трубопровода процесса в ш в цикле?

Я попытался это, но получил "неоднозначной перенаправлять" ошибка:

#!/bin/sh 

while read line; do 
    echo "$line" 
    # do stuff with $line 
done < $(perl process.pl) 

./script.sh : line 6: $(perl process.pl): ambiguous redirect 

Например, один (неэффективное) решение будет:

#!/bin/sh 

tmpFile=/tmp/tmpFile.txt 
perl process.pl > $tmpFile 
while read line; do 
    echo "$line" 
    # do stuff with $line 
done < $tmpFile 

Я знаю, что я могу трубы процесс Perl к while петли, как:

perl process.pl | while ... 

, но цикл в то время как выполняется в субоболочке , и мне нужно, чтобы некоторые переменные, установленные в цикле while, оставались после завершения цикла, поэтому это не вариант.

Что я могу сделать?

ответ

2

Вы почти у цели. Попробуйте это:

while read -r line; do 
    echo "$line" 
    # do stuff with $line 
done < <(perl process.pl) 

Единственным отличием является < вместо $.

$(cmd) - это подстановка команд, которая расширяется до выхода команды в круглых скобках. С другой стороны, <(cmd) является process substitution. Обратите внимание, что это расширение Bash, поэтому вы также должны изменить свой shebang на #!/bin/bash, если вы хотите использовать этот метод.

В качестве альтернативы, если вы не используете Bash, вы можете просто использовать трубу вместо:

perl process.pl | while read -r line; do 
    echo "$line" 
    # do stuff with $line 
done 

как в сторону, you almost always want to use the -r switch with read

+1

OP-shebang - это '#!/Bin/sh' ... но OP упоминает Bash и помеченный вопрос Bash ... запутанный (особенно замены процесса для Bash, а не оболочек POSIX). –

+0

На самом деле, решение «pipe» было первым, что я придумал. Тем не менее, это выполняет процесс в подоболочке, и я теряю любые переменные, измененные в '# do stuff с $ line' – asf107

+0

@ asf107 Я не уверен, что вы подразумеваете под« Я теряю все, что происходит ». Вы можете перенаправить вывод цикла, если хотите? –

1

Используйте here-document:

while IFS= read -r line; do 
    echo "$line" 
    # do stuff with $line 
done <<EOF 
$(perl process.pl) 
EOF 
2

Используйте именованный канал; bash замещение процесса по существу является синтаксическим сахаром вокруг этого.

mkfifo output 
perl process.pl > output & 
while IFS= read -r line; do 
    echo "$line" 
    # do stuff with $line 
done < output 
rm output 

Названная труба не требует process.pl завершить до петли while начинает потреблять выход.

+0

интересно, я даже не знал, что такая вещь существует :) спасибо! – asf107

Смежные вопросы