2016-04-28 2 views
1

Использование Eval на строку, которая содержит команду, которая определяет функцию работает без проблем:Почему `eval` не работает внутри моей петли?

$ eval "p4() { echo 4; }" 
$ p4 
4 

Однако, когда я делаю это так, что больше не работает:

$ echo 'p3() { echo 3; }' | while read line ; do eval "$line"; done 
$ p3 
-bash: p3: command not found 

Почему не эта работа?

+0

Я не уверен, что вы должны играть с 'eval', если вы еще не понимаете подоболочек. – chepner

ответ

8

Это происходит из-за того, что суб-оболочка создается из-за вашего конвейера после echo. Это объявление функции p3 в под-оболочке, недоступной из текущей (родительской) оболочки.

Вы можете избежать этого, используя здесь-нить вместо трубопровода:

while read line ; do eval "$line"; done <<< 'p3() { echo 3; }' 

p3 
3 
3

От man bash:

Каждая команда в конвейере выполняется как отдельный процесс (то есть, в субоболочке).

Поскольку переменные не передаются на подоболочку, p3 там недоступен.

В качестве альтернативы: zsh выполняет второй пример точно так, как вы ожидали, то есть выводит 3.

4

Что говорит anubhava, и вы всегда должны помнить об этом. Позвольте мне предложить альтернативу: вы можете использовать подстановку процесса и source:

source <(echo 'p3() { echo 3; }') 
p3 

вопрос, почему вы хотите сделать это?

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