Между следующими альтернативами ...
с
eval
.comd="ls" eval "$comd"
с
source /dev/stdin
printf "ls" | source /dev/stdin
с
source /dev/stdin
и( )
или{ }
( printf "ls" ) | source /dev/stdin { printf "ls"; } | source /dev/stdin
(Когда мы бежим
printf
в{ }
, есть какие - либо преимущества, кроме не используя подоболочку?)В чем разница между ними?
Что является предпочтительным?
Какой способ запуска команд является предпочтительным?
()
или{}
?
bash
command-line
MS.Kim
источник
источник
Ответы:
от
bash manpage
:Там нет различий между двумя способами.
Есть только одно замечание:
eval
объединены все его аргументы, которые затем запускаются как одна команда.source
читает содержимое файла и выполняет их.eval
может только строить команды из своих аргументов, а неstdin
. Таким образом, вы не можете сделать так:Ваш пример дает тот же результат, но цель
eval
иsource
отличается.source
обычно используется для предоставления библиотеки для других сценариев, аeval
используется только для оценки команд. Вы должны избегать использования,eval
если это возможно, потому что нет гарантии, что очищенная строка является чистой; мы должны сделать некоторые проверки вменяемости, используяsubshell
вместо этого.Когда вы запускаете команды sequence внутри фигурной скобки
{ }
, все команды запускаются в текущей оболочке , а не в подоболочке (что имеет место, если вы запускаете в скобках (см. Ссылку на bash )).Использование
subshell ( )
использует больше ресурсов, но ваша текущая среда не затронута. Использование{ }
запускает все команды в текущей оболочке, так что это влияет на вашу среду. В зависимости от вашей цели вы можете выбрать один из них.источник
eval
наsource
. Я предполагаю, что вопрос:eval "$cmd"
эквивалентенecho "$cmd" | source /dev/stdin
. Мое текущее мнение: да.Основное отличие состоит в том, что во 2-й и 3-й формах используется конвейер, который заставит bash запустить команду «source» в подоболочке (если не задан lastpipe, доступный только в bash 4.2+), что сделает его в значительной степени эквивалентным :
В результате любые переменные среды, установленные вашим кодом, будут потеряны, поэтому это не будет работать должным образом:
Для запуска команд в текущей оболочке вы можете использовать подстановку процесса:
Вы можете поместить больше команд в круглые скобки, используя точку с запятой, как обычно.
Если вы устраните канал таким образом, я думаю, что нет никакой разницы между использованием «eval» и «source». Вы должны предпочесть тот, который проще использовать в вашем конкретном случае:
источник
В качестве дополнения к ответам уже даны:
source
Эквивалентно ...... является ...
В случае,
ls
если нет существенной разницы.Но в случае команды, которая предназначена для воздействия на вашу текущую среду (то, что вы обычно подразумеваете при использовании
source
), этот вариант будет делать это (как и ваше первое решение с этимeval
), в то время как ваш второй подход просто влияет на среду подоболочки, которая выиграла ' быть доступным после выполнения вашей строки кода.источник