Используйте, type commandчтобы узнать, какой тип команды . ( type evalв этом случае)
rozcietrzewiacz
9
«Eval - это встроенная оболочка»
Нуно Рафаэль Фигейредо
3
help evalполучить страницу "man" из вашей оболочки
m-ric
eval встроен в bash и задокументирован на странице руководства bash. Так что просто наберите "man bash" и найдите соответствующий раздел для eval. Это относится и к другим bash-buildins тоже.
Дирк Таннхойзер
Ответы:
132
evalявляется частью POSIX. Это интерфейс, который может быть встроенным в оболочку.
В терминологии оболочки evalэто встроенная функция, а не функция. На практике встроенные модули ведут себя во многом подобно функциям, которые не имеют определения на языке, но не совсем (что становится очевидным, если вы достаточно искривлены, чтобы определить вызываемую функцию eval).
Жиль
спасибо, исправил это :-)
echox
4
В чем разница между eval и backticks`?
JohnyTex
5
Обратные метки - это сокращение для выполнения еще одной целой оболочки, означающее, что в вашем скрипте будет запущен еще один дочерний процесс bash / sh.
Аарон Р.
Почему echo $ y (этап 3) возвращает foo (10) вместо $ foo? (т.е. просто значение foo вместо строки $ + значение foo)?
JohnDoea
60
Да, evalэто внутренняя команда bash, поэтому она описана на bashстранице руководства .
eval[arg ...]The args are read and concatenated together into a single com-
mand.This command is then read and executed by the shell, and
its exit status is returned as the value of eval.If there are
no args, or only null arguments,eval returns 0.
Обычно он используется в сочетании с подстановкой команд . Без явного eval, оболочка пытается выполнить результат подстановки команды, а не оценить его.
Скажите, что вы хотите закодировать эквивалент VAR=value; echo $VAR. Обратите внимание на разницу в том, как оболочка обрабатывает записи echo VAR=value:
andcoz@...:~> $( echo VAR=value )
bash: VAR=value: command not found
andcoz@...:~> echo $VAR<empty line>
Оболочка пытается выполнить echoи VAR=valueдве отдельные команды. Выдает ошибку о второй строке. Назначение остается неэффективным.
andcoz@...:~>eval $( echo VAR=value )
andcoz@...:~> echo $VAR
value
Оболочка объединяет (объединяет) две строки echoи VAR=valueанализирует эту единицу в соответствии с соответствующими правилами и выполняет ее.
Последнее, но не менее важное, evalможет быть очень опасной командой. Любой ввод в evalкоманду должен быть тщательно проверен, чтобы избежать проблем безопасности.
evalне имеет man-страницы, потому что это не отдельная внешняя команда, а скорее встроенная оболочка, то есть команда, внутренняя и известная только shell ( bash). Соответствующая часть bashсправочной страницы гласит:
eval[arg ...]The args are read and concatenated together into a single command.This command is then read and executed by the shell, and its exit
status is returned as the value of eval.If there are no args, or only
null arguments,eval returns 0
Кроме того, вывод, если help evalэто:
eval:eval[arg ...]Execute arguments as a shell command.CombineARGs into a single string, use the result as input to the shell,
and execute the resulting commands.ExitStatus:Returns exit status of command or success if command is null.
evalэто мощная команда, и если вы намереваетесь ее использовать, вы должны быть очень осторожны, чтобы не допустить возможных рисков безопасности, связанных с ней.
Оператор eval говорит оболочке принять аргументы eval в качестве команды и выполнить их через командную строку. Это полезно в ситуации как ниже:
В вашем скрипте, если вы определяете команду в переменную, а затем хотите использовать эту команду, тогда вы должны использовать eval:
/home/user1 > a="ls | more"/home/user1 > $a
bash: command not found: ls | more/home/user1 ># Above command didn't work as ls tried to list file with name pipe (|) and more. But these files are not there/home/user1 >eval $a
file.txt
mailids
remote_cmd.sh
sample.txt
tmp/home/user1 >
Комментарий в строке 4 вашего примера неправильный: это должно быть «Команда выше не работала, потому что bash пытался найти вызываемую команду ls | more. Другими словами: одно имя команды состояло из девяти символов, включая пробелы и символ канала» .
CFI
Я поступаю точно так же, как он сообщил. bash --version == GNU bash, версия 3.2.57 (1) -релиз (x86_64-apple-darwin18)
Александр Бёрд
10
Что такое Eval?
eval - это команда оболочки, которая обычно реализуется как встроенная.
Термин «встроенный» подразумевает, что оболочка может запускать утилиту напрямую и не нуждается в ее поиске.
Что оно делает?
Проще говоря: делает входную строку для анализа дважды .
Как оно это делает?
Оболочка имеет последовательность шагов, которые следует выполнить для «обработки» строки. Вы можете посмотреть на это изображение и понять, что eval - это единственная линия, которая идет вверх, к шагу 1 слева. Из описания POSIX :
2.1 Shell Введение
Оболочка читает свой ввод ....
Оболочка разбивает входные данные на токены: слова и операторы
Оболочка анализирует ввод в простые и составные команды.
Оболочка выполняет различные расширения (отдельно) ...
Оболочка выполняет перенаправление и удаляет операторы перенаправления и их операнды из списка параметров.
Оболочка выполняет функцию, встроенный, исполняемый файл или скрипт ...
Оболочка по желанию ожидает завершения команды и собирает статус выхода.
На шаге 6 будет выполнен встроенный.
На шаге 6 eval вызывает отправку обработанной строки обратно на шаг 1.
Это единственное условие, при котором последовательность выполнения возвращается назад.
Вот почему я говорю: с eval входная строка анализируется дважды .
Эффекты разбора дважды.
Первый.
И самый важный эффект, чтобы понять. Является ли это следствием того, что в первый раз строка подвергается семи шагам оболочки, показанным выше, это цитирование . Внутри шага 4 (расширения) также есть последовательность шагов для выполнения всех расширений , последним из которых является Удаление цитаты :
Удаление цитаты всегда должно выполняться последним.
Таким образом, всегда есть один уровень цитирования удален.
Во-вторых.
Как следствие этого первого эффекта, дополнительные / различные части строки становятся доступными для разбора оболочки и всех других шагов.
Пример.
Косвенность.
Что позволяет выполнять косвенные расширения:
a=b b=c ;eval echo \$$a ### shall produce "c"
Почему? Потому что в первом цикле первый $цитируется.
Как таковой, он игнорируется для расширений оболочкой.
Следующий $с именем а раскрывается до «б».
Затем один уровень цитирования удаляется, в результате чего первый не $цитируется.
Конец первого цикла.
Затем во втором цикле строка $bчитается оболочкой.
Затем расширили до «с»
и дали в качестве аргумента echo.
Чтобы «увидеть», что eval будет производить в первом цикле (чтобы его можно было снова оценить), используйте echo. Или любая команда / скрипт / программа, которая четко показывает аргументы:
$ a=b b=c
$ eval echo \$$a;
c
Замените eval на echo, чтобы «увидеть», что происходит:
$ echo echo \$$a
echo $b
Также можно показать все «части» строки с помощью:
$ printf '<%s> ' echo \$$a
<echo><$b>
В этом примере это только одно эхо и одна переменная, но помните об этом, чтобы помочь в оценке более сложных случаев.
Исправление
Надо сказать, что: в приведенном выше коде есть ошибка, вы это видите?
Легко: отсутствуют некоторые цитаты.
Как? Вы можете спросить. Все просто, давайте изменим переменные (не код):
$ a=b b="hi jk"
$ eval echo \$$a
hi jk
Видишь пропущенные места?
Это потому, что значение внутри $bбыло разделено оболочкой.
Если это не убедит вас, попробуйте это:
$ a=b b="hi * jk"
$ eval echo \$$a ### warning this will expand to the list ### of all files in the present directory.
Почему?
Отсутствующие цитаты. Чтобы он работал правильно (добавьте внутренние "$a"и внешние \"кавычки).
Попробуйте это (совершенно безопасно):
$ a=b b="hi * jk"
$ eval echo \" \$"$a" \"
hi * jk
О руководстве:
Для этого нет справочной страницы ..
Нет, для этого нет независимой справочной страницы. Поиск руководства с man -f evalили даже не apropos evalпоказывать запись.
Он включен внутри man bash. Как и любой встроенный.
Ищите «SHELL BUILTIN COMMANDS», а затем «eval».
Более простой способ получить помощь: в bash вы можете help evalобратиться за помощью к встроенному.
Почему Эвал называют злом?
Потому что это привязка текста к коду динамически.
Другими словами: он преобразует список своих аргументов (и / или расширений таких аргументов) в исполняемую строку. Если по какой-либо причине злоумышленник установил аргумент, вы будете выполнять код злоумышленника.
Или даже проще, с помощью eval вы говорите, кто бы ни определил значение одного или нескольких аргументов:
Да ладно, сядь здесь и набери любую командную строку, я выполню ее своими силами.
Это опасно? Всем должно быть ясно, что это так.
Правило безопасности для eval должно быть таким:
Выполняйте eval только для переменных, которым вы дали его значение.
evalявляется чертой большинства интерпретируемых языков ( TCL, python, ruby...), а не только снаряды. Он используется для динамической оценки кода.
В оболочках это реализовано как встроенная команда оболочки.
По сути, evalпринимает строку в качестве аргумента и оценивает / интерпретирует код в ней. В оболочках evalможет принимать более одного аргумента, но evalпросто объединяет их для формирования строки для оценки.
Он очень мощный, потому что вы можете динамически создавать код и запускать его, чего вы не можете делать в скомпилированных языках, таких как C.
Подобно:
varname=$1 varvalue=$2
eval"$varname=\$varvalue"# evaluate a string like "foo=$varvalue"# which in Bourne-like shell language# is a variable assignment.
Но это также опасно, так как важно очистить динамические (предоставляемые извне) части того, что передается, по evalтой причине, что это интерпретируется как шелл-код.
Например, выше, если $1есть evil-command; var, evalв конечном итоге evil-command; var=$varvalueоцените код оболочки и затем запустите его evil-command.
Злобность evalчасто преувеличивается.
ОК, это опасно, но, по крайней мере, мы знаем, что это опасно.
Много других команд будет оценивать код оболочки в его аргументы , если не продезинфицировать, например , ( в зависимости от оболочки), [он же test, export, printf, GNU sed, awkи, конечно , sh/ bash/ perlи все переводчики ...
Примеры (здесь используются unameкак не предоставленные извне данные, так evil-commandи $aпредоставленные извне):
Эти sed, export... команды могут считаться более опасными, потому что, хотя это очевидно eval "$var", из-за того, что содержимое $varбудет оцениваться как шелл-код, это не так очевидно с sed "s/foo/$var/"или export "$var=value"или [ "$var" -gt 0 ]. Опасность та же, но она скрыта в других командах.
@BinaryZebra, sedподобно тому, как evalпередается строка, содержащаяся в переменной, и для обоих, содержимое этой строки в конечном итоге оценивается как шелл-код, поэтому sedэто так же опасно, как evalи я. sedпередается строка, содержащая uname(uname не был выполнен до сих пор) и через вызов sed, команда uname заканчивается выполнением. Как для Eval. Во- sed 's/foo/$a/g'первых, вы не передаете неанимированные данные sed, это не то, о чем мы здесь говорим.
Спасибо за ваш вклад, но, как бы они ни были интересны, нам не очень интересно составлять список (немного других) примеров использования eval. Верите ли вы, что есть какой-то фундаментальный, критический аспект функциональности, evalкоторый не описан в существующих ответах? Если так, то объясните это и используйте пример, чтобы проиллюстрировать ваше объяснение. Пожалуйста, не отвечайте в комментариях; отредактируйте свой ответ, чтобы сделать его более понятным и полным.
type command
чтобы узнать, какой тип команды . (type eval
в этом случае)help eval
получить страницу "man" из вашей оболочкиОтветы:
eval
является частью POSIX. Это интерфейс, который может быть встроенным в оболочку.Это описано в «Руководстве программиста POSIX»: http://www.unix.com/man-page/posix/1posix/eval/
Он примет аргумент и создаст его команду, которая будет выполняться оболочкой. Вот пример справочной страницы:
$foo
значение'10'
и$x
значение'foo'
.$y
, из чего состоит строка'$foo'
. Знак доллара должен быть экранирован'$'
.echo $y
.'$foo'
eval
. Сначала он будет оцениваться$x
в строку'foo'
. Теперь у нас есть утверждение,y=$foo
которое будет оцененоy=10
.echo $y
теперь является значением'10'
.Это распространенная функция во многих языках, например, Perl и JavaScript. Посмотрите на perldoc eval для других примеров: http://perldoc.perl.org/functions/eval.html
источник
eval
это встроенная функция, а не функция. На практике встроенные модули ведут себя во многом подобно функциям, которые не имеют определения на языке, но не совсем (что становится очевидным, если вы достаточно искривлены, чтобы определить вызываемую функциюeval
).Да,
eval
это внутренняя команда bash, поэтому она описана наbash
странице руководства .Обычно он используется в сочетании с подстановкой команд . Без явного
eval
, оболочка пытается выполнить результат подстановки команды, а не оценить его.Скажите, что вы хотите закодировать эквивалент
VAR=value; echo $VAR
. Обратите внимание на разницу в том, как оболочка обрабатывает записиecho VAR=value
:Оболочка пытается выполнить
echo
иVAR=value
две отдельные команды. Выдает ошибку о второй строке. Назначение остается неэффективным.echo
иVAR=value
анализирует эту единицу в соответствии с соответствующими правилами и выполняет ее.Последнее, но не менее важное,
eval
может быть очень опасной командой. Любой ввод вeval
команду должен быть тщательно проверен, чтобы избежать проблем безопасности.источник
eval
не имеет man-страницы, потому что это не отдельная внешняя команда, а скорее встроенная оболочка, то есть команда, внутренняя и известная только shell (bash
). Соответствующая частьbash
справочной страницы гласит:Кроме того, вывод, если
help eval
это:eval
это мощная команда, и если вы намереваетесь ее использовать, вы должны быть очень осторожны, чтобы не допустить возможных рисков безопасности, связанных с ней.источник
Оператор eval говорит оболочке принять аргументы eval в качестве команды и выполнить их через командную строку. Это полезно в ситуации как ниже:
В вашем скрипте, если вы определяете команду в переменную, а затем хотите использовать эту команду, тогда вы должны использовать eval:
источник
ls | more
. Другими словами: одно имя команды состояло из девяти символов, включая пробелы и символ канала» .Что такое Eval?
eval - это команда оболочки, которая обычно реализуется как встроенная.
В POSIX он указан как часть «2.14. Специальные встроенные утилиты» в записи «eval» .
Что означает встроенное:
Что оно делает?
Проще говоря: делает входную строку для анализа дважды .
Как оно это делает?
Оболочка имеет последовательность шагов, которые следует выполнить для «обработки» строки. Вы можете посмотреть на это изображение и понять, что eval - это единственная линия, которая идет вверх, к шагу 1 слева. Из описания POSIX :
На шаге 6 будет выполнен встроенный.
На шаге 6 eval вызывает отправку обработанной строки обратно на шаг 1.
Это единственное условие, при котором последовательность выполнения возвращается назад.
Эффекты разбора дважды.
Первый.
И самый важный эффект, чтобы понять. Является ли это следствием того, что в первый раз строка подвергается семи шагам оболочки, показанным выше, это цитирование . Внутри шага 4 (расширения) также есть последовательность шагов для выполнения всех расширений , последним из которых является Удаление цитаты :
Таким образом, всегда есть один уровень цитирования удален.
Во-вторых.
Как следствие этого первого эффекта, дополнительные / различные части строки становятся доступными для разбора оболочки и всех других шагов.
Пример.
Косвенность.
Что позволяет выполнять косвенные расширения:
Почему? Потому что в первом цикле первый
$
цитируется.Как таковой, он игнорируется для расширений оболочкой.
Следующий
$
с именем а раскрывается до «б».Затем один уровень цитирования удаляется, в результате чего первый не
$
цитируется.Конец первого цикла.
Затем во втором цикле строка
$b
читается оболочкой.Затем расширили до «с»
и дали в качестве аргумента
echo
.Чтобы «увидеть», что eval будет производить в первом цикле (чтобы его можно было снова оценить), используйте echo. Или любая команда / скрипт / программа, которая четко показывает аргументы:
Замените eval на echo, чтобы «увидеть», что происходит:
Также можно показать все «части» строки с помощью:
В этом примере это только одно эхо и одна переменная, но помните об этом, чтобы помочь в оценке более сложных случаев.
Исправление
Надо сказать, что: в приведенном выше коде есть ошибка, вы это видите?
Легко: отсутствуют некоторые цитаты.
Как? Вы можете спросить. Все просто, давайте изменим переменные (не код):
Видишь пропущенные места?
Это потому, что значение внутри
$b
было разделено оболочкой.Если это не убедит вас, попробуйте это:
Почему?
Отсутствующие цитаты. Чтобы он работал правильно (добавьте внутренние
"$a"
и внешние\"
кавычки).Попробуйте это (совершенно безопасно):
О руководстве:
Нет, для этого нет независимой справочной страницы. Поиск руководства с
man -f eval
или даже неapropos eval
показывать запись.Он включен внутри
man bash
. Как и любой встроенный.Ищите «SHELL BUILTIN COMMANDS», а затем «eval».
Более простой способ получить помощь: в bash вы можете
help eval
обратиться за помощью к встроенному.Почему Эвал называют злом?
Потому что это привязка текста к коду динамически.
Другими словами: он преобразует список своих аргументов (и / или расширений таких аргументов) в исполняемую строку. Если по какой-либо причине злоумышленник установил аргумент, вы будете выполнять код злоумышленника.
Или даже проще, с помощью eval вы говорите, кто бы ни определил значение одного или нескольких аргументов:
Это опасно? Всем должно быть ясно, что это так.
Правило безопасности для eval должно быть таким:
Выполняйте eval только для переменных, которым вы дали его значение.
Подробнее читайте здесь .
источник
eval
является чертой большинства интерпретируемых языков (TCL
,python
,ruby
...), а не только снаряды. Он используется для динамической оценки кода.В оболочках это реализовано как встроенная команда оболочки.
По сути,
eval
принимает строку в качестве аргумента и оценивает / интерпретирует код в ней. В оболочкахeval
может принимать более одного аргумента, ноeval
просто объединяет их для формирования строки для оценки.Он очень мощный, потому что вы можете динамически создавать код и запускать его, чего вы не можете делать в скомпилированных языках, таких как C.
Подобно:
Но это также опасно, так как важно очистить динамические (предоставляемые извне) части того, что передается, по
eval
той причине, что это интерпретируется как шелл-код.Например, выше, если
$1
естьevil-command; var
,eval
в конечном итогеevil-command; var=$varvalue
оцените код оболочки и затем запустите егоevil-command
.Злобность
eval
часто преувеличивается.ОК, это опасно, но, по крайней мере, мы знаем, что это опасно.
Много других команд будет оценивать код оболочки в его аргументы , если не продезинфицировать, например , ( в зависимости от оболочки),
[
он жеtest
,export
,printf
, GNUsed
,awk
и, конечно ,sh
/bash
/perl
и все переводчики ...Примеры (здесь используются
uname
как не предоставленные извне данные, такevil-command
и$a
предоставленные извне):Эти
sed
,export
... команды могут считаться более опасными, потому что, хотя это очевидноeval "$var"
, из-за того, что содержимое$var
будет оцениваться как шелл-код, это не так очевидно сsed "s/foo/$var/"
илиexport "$var=value"
или[ "$var" -gt 0 ]
. Опасность та же, но она скрыта в других командах.источник
sed
подобно тому, какeval
передается строка, содержащаяся в переменной, и для обоих, содержимое этой строки в конечном итоге оценивается как шелл-код, поэтомуsed
это так же опасно, какeval
и я.sed
передается строка, содержащаяuname
(uname не был выполнен до сих пор) и через вызовsed
, команда uname заканчивается выполнением. Как для Eval. Во-sed 's/foo/$a/g'
первых, вы не передаете неанимированные данныеsed
, это не то, о чем мы здесь говорим.Этот пример может пролить некоторый свет:
Вывод скрипта выше:
источник
eval
. Верите ли вы, что есть какой-то фундаментальный, критический аспект функциональности,eval
который не описан в существующих ответах? Если так, то объясните это и используйте пример, чтобы проиллюстрировать ваше объяснение. Пожалуйста, не отвечайте в комментариях; отредактируйте свой ответ, чтобы сделать его более понятным и полным.