Use type commandpara saber de que tipo é um comando . ( type evalneste caso)
rozcietrzewiacz 22/10
9
"eval é um shell embutido"
Nuno Rafael Figueiredo
3
help evalpara obter página "man" do seu shell
m-ric
eval é um bash-builtin e está documentado na página de manual do bash. Então, basta digitar "man bash" e procurar a seção apropriada para eval. Isso também se aplica a outros bash-builtins.
Dirk Thannhäuser
Respostas:
132
evalfaz parte do POSIX. É uma interface que pode ser um shell embutido.
Na terminologia do shell, evalé um recurso interno, não uma função. Na prática, os built-ins se comportam muito como funções que não têm uma definição na linguagem, mas não tanto (como fica aparente se você tiver distorção suficiente para definir uma função chamada eval).
Gilles
thx, corrigiu isso :-)
echox 25/10
4
Qual é a diferença entre eval e backticks `?
JohnyTex
5
Backticks são atalhos para executar outro shell inteiro, o que significa que você terá outro processo filho bash / sh em execução no seu script.
Aaron R.
Por que eco $ y (estágio 3) traz de volta foo (10) em vez de $ foo? (ou seja, apenas o valor de foo em vez da string $ + o valor de foo)?
JohnDoea
60
Sim, evalé um comando interno do bash, portanto, é descrito na bashpágina de manual.
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.
Geralmente é usado em combinação com uma substituição de comando . Sem um explícito eval, o shell tenta executar o resultado de uma substituição de comando, não para avaliá- lo.
Diga que deseja codificar um equivalente a VAR=value; echo $VAR. Observe a diferença de como o shell lida com os escritos de echo VAR=value:
andcoz@...:~> $( echo VAR=value )
bash: VAR=value: command not found
andcoz@...:~> echo $VAR
<empty line>
O shell tenta executar echoe VAR=valuecomo dois comandos separados. Emite um erro sobre a segunda string. A atribuição permanece ineficaz.
andcoz@...:~>eval $( echo VAR=value )
andcoz@...:~> echo $VAR
value
O shell mescla (concatena) as duas seqüências echoe VAR=valueanalisa essa unidade única de acordo com as regras apropriadas e a executa.
Por último, mas não menos importante, evalpode ser um comando muito perigoso. Qualquer entrada em um evalcomando deve ser cuidadosamente verificada para evitar problemas de segurança.
evalnão possui uma página de manual porque não é um comando externo separado, mas um shell interno, o que significa um comando interno e conhecido apenas pelo shell ( bash). A parte relevante da bashpágina de manual diz:
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
Além disso, a saída se 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é um comando poderoso e, se você pretende usá-lo, deve ter muito cuidado para evitar os possíveis riscos de segurança que o acompanham.
A instrução eval diz ao shell para pegar os argumentos de eval como comando e executá-los na linha de comando. É útil em uma situação como abaixo:
No seu script, se você estiver definindo um comando em uma variável e, posteriormente, desejar usar esse comando, use 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 >
O comentário na linha 4 do seu exemplo está errado: O comando acima não funcionou porque o bash tentou encontrar um comando chamado ls | more. Em outras palavras: O nome do comando único consistia em nove caracteres, incluindo os espaços e o símbolo de barra vertical .
TPI
Eu recebo exatamente o mesmo comportamento que ele relatou. bash --version == GNU bash, versão 3.2.57 (1) -release (x86_64-apple-darwin18)
Alexander Bird
10
O que é eval?
eval é um comando shell que geralmente é implementado como um componente interno.
O termo "interno" implica que o shell pode executar o utilitário diretamente e não precisa procurá-lo.
O que isso faz?
Em termos simples: faz com que uma linha de entrada seja analisada duas vezes .
Como isso acontece?
O shell possui uma sequência de etapas a seguir para "processar" uma linha. Você pode olhar para esta imagem e perceber que eval é a única linha que sobe de volta à etapa 1, à esquerda. Na descrição do POSIX :
2.1 Introdução ao Shell
O shell lê sua entrada ....
O shell divide a entrada em tokens: palavras e operadores
O shell analisa a entrada em comandos simples e compostos.
O shell realiza várias expansões (separadamente) ...
O shell executa o redirecionamento e remove os operadores de redirecionamento e seus operandos da lista de parâmetros.
O shell executa uma função, arquivo executável interno ou script ...
Opcionalmente, o shell aguarda a conclusão do comando e coleta o status de saída.
Na etapa 6, um built-in será executado.
Na etapa 6, eval faz com que a linha processada seja enviada de volta para a etapa 1.
É a única condição sob a qual a sequência de execução retorna.
É por isso que digo: Com eval, uma linha de entrada é analisada duas vezes .
Efeitos da análise duas vezes.
O primeiro.
E efeito mais importante para entender. É que uma consequência da primeira vez que uma linha está sujeita às sete passos shell mostrados acima, está citando . Na etapa 4 (expansões), também há uma sequência de etapas para executar todas as expansões , a última das quais é Remoção de cotação :
A remoção da cotação deve sempre ser realizada por último.
Portanto, sempre, há um nível de cotação removido.
Segundo.
Como conseqüência desse primeiro efeito, partes adicionais / diferentes da linha ficam expostas à análise de shell e a todas as outras etapas.
Exemplo.
Indirection.
Isso permite executar expansões indiretas:
a=b b=c ;eval echo \$$a ### shall produce "c"
Por quê? Porque no primeiro loop, o primeiro $é citado.
Como tal, é ignorado para expansões pelo shell.
O próximo $com o nome a é expandido para produzir "b".
Em seguida, um nível de citação é removido, tornando o primeiro $não citado.
Fim do primeiro loop.
É então, no segundo loop, que a string $bé lida pelo shell.
Então expandido para "c"
E dado como argumento para echo.
Para "ver" o que o eval produzirá no primeiro loop (para ser avaliado novamente), use echo. Ou qualquer comando / script / programa que mostre claramente os argumentos:
$ a=b b=c
$ eval echo \$$a;
c
Substitua eval por eco para "ver" o que está acontecendo:
$ echo echo \$$a
echo $b
Também é possível mostrar todas as "partes" de uma linha com:
$ printf '<%s> ' echo \$$a
<echo><$b>
Que, neste exemplo, é apenas um eco e uma variável, mas lembre-se de ajudar na avaliação de casos mais complexos.
Uma correção
Deve-se dizer que: há um erro no código acima, você vê?
Fácil: faltam algumas aspas.
Quão? você pode perguntar. Simples, vamos mudar as variáveis (não o código):
$ a=b b="hi jk"
$ eval echo \$$a
hi jk
Veja os espaços que faltam?
Isso ocorre porque o valor interno $bfoi dividido pelo shell.
Se isso não o convencer, tente o seguinte:
$ a=b b="hi * jk"
$ eval echo \$$a ### warning this will expand to the list ### of all files in the present directory.
Por quê?
Citações ausentes. Para fazê-lo funcionar corretamente (adicione aspas internas "$a"e externas \").
Tente isto (é perfeitamente seguro):
$ a=b b="hi * jk"
$ eval echo \" \$"$a" \"
hi * jk
Sobre o manual:
Não existe uma página de manual para isso ..
Não, não há uma página de manual independente para isso. A pesquisa de manual com man -f evalou mesmo apropos evalnão mostra entrada.
Está incluído no interior man bash. Como é qualquer embutido.
Procure por "SHELL BUILTIN COMMANDS" e depois por "eval".
Uma maneira mais fácil de obter ajuda é: No bash, você pode fazer help evalpara ver a ajuda do built-in.
Por que eval é chamado de mal?
Porque está vinculando o texto ao código dinamicamente.
Em outras palavras: converte a lista de seus argumentos (e / ou expansões de tais argumentos) em uma linha executada. Se, por qualquer motivo, um argumento tiver sido definido por um invasor, você estará executando o código do invasor.
Ou ainda mais simples: com eval, você está dizendo a quem definiu o valor de um ou vários argumentos:
Vamos, sente-se aqui e digite qualquer linha de comando, eu irei executá-lo com meus poderes.
Isso é perigoso? Deve ser claro para todos que é.
A regra de segurança para eval deve ser:
Execute eval apenas nas variáveis às quais você deu valor.
evalé uma característica das línguas mais interpretadas ( TCL, python, ruby...), não apenas conchas. É usado para avaliar o código dinamicamente.
Em shells, é implementado como um comando embutido no shell.
Basicamente, evalpega uma string como argumento e avalia / interpreta o código nela. Em shells, evalpode levar mais de um argumento, mas evalapenas concatena aqueles para formar a string a ser avaliada.
É muito poderoso porque você pode construir código dinamicamente e executá-lo, algo que não pode ser feito em linguagens compiladas como C.
Gostar:
varname=$1 varvalue=$2
eval"$varname=\$varvalue"# evaluate a string like "foo=$varvalue"# which in Bourne-like shell language# is a variable assignment.
Mas também é perigoso, pois é importante higienizar as partes dinâmicas (fornecidas externamente) do que é passado evalpelo mesmo motivo que é interpretado como código do shell.
Por exemplo, acima de se $1for evil-command; var, evalacabaria avaliando o evil-command; var=$varvaluecódigo do shell e o executaria evil-command.
A maldade de evalmuitas vezes é exagerada.
OK, é perigoso, mas pelo menos sabemos que é perigoso.
Um monte de outros comandos irá avaliar o código shell em seus argumentos, se não higienizado, como (dependendo do shell), [aka test, export, printf, GNU sed, awke, claro, sh/ bash/ perle todos os intérpretes ...
Exemplos (aqui usando unamecomo os evil-commande $acomo dados não autorizados fornecidos externamente):
Aqueles sed, export... comandos poderia ser considerado mais perigoso porque enquanto é óbvio eval "$var"fará com que o conteúdo $vara ser avaliado como código shell, não é tão óbvio com sed "s/foo/$var/"ou export "$var=value"ou [ "$var" -gt 0 ]. A perigosidade é a mesma, mas está oculta nesses outros comandos.
O @BinaryZebra, sedcomo evalestá sendo passado uma string contida em uma variável, e para ambos, o conteúdo dessa string acaba sendo avaliado como código shell, então sedé tão perigoso quanto eval, é o que estou dizendo. sedestá passando uma string contendo uname(uname ainda não foi executado) e, através da invocação de sed, o comando uname acaba sendo executado. Como para avaliação. Em sed 's/foo/$a/g', você não está transmitindo dados não autorizados sed, não é disso que estamos falando aqui.
Obrigado pela sua contribuição, mas, por mais divertidos que sejam, não estamos realmente interessados em compilar uma lista de exemplos (um pouco diferentes) de uso eval. Você acredita que há algum aspecto fundamental e fundamental da funcionalidade evalque não é abordado nas respostas existentes? Nesse caso, explique -o e use o exemplo para ilustrar sua explicação. Por favor, não responda nos comentários; edite sua resposta para torná-la mais clara e completa.
type command
para saber de que tipo é um comando . (type eval
neste caso)help eval
para obter página "man" do seu shellRespostas:
eval
faz parte do POSIX. É uma interface que pode ser um shell embutido.Está descrito no "Manual do Programador POSIX": http://www.unix.com/man-page/posix/1posix/eval/
Vai pegar um argumento e construir um comando dele, que será executado pelo shell. Este é o exemplo da página de manual:
$foo
com o valor'10'
e$x
com o valor'foo'
.$y
, que consiste na string'$foo'
. O cifrão deve ser escapado com'$'
.echo $y
,.'$foo'
eval
. Ele primeiro avaliará$x
a string'foo'
. Agora, temos a declaraçãoy=$foo
que será avaliaday=10
.echo $y
agora é o valor'10'
.Essa é uma função comum em muitos idiomas, por exemplo, Perl e JavaScript. Veja perldoc eval para mais exemplos: http://perldoc.perl.org/functions/eval.html
fonte
eval
é um recurso interno, não uma função. Na prática, os built-ins se comportam muito como funções que não têm uma definição na linguagem, mas não tanto (como fica aparente se você tiver distorção suficiente para definir uma função chamadaeval
).Sim,
eval
é um comando interno do bash, portanto, é descrito nabash
página de manual.Geralmente é usado em combinação com uma substituição de comando . Sem um explícito
eval
, o shell tenta executar o resultado de uma substituição de comando, não para avaliá- lo.Diga que deseja codificar um equivalente a
VAR=value; echo $VAR
. Observe a diferença de como o shell lida com os escritos deecho VAR=value
:O shell tenta executar
echo
eVAR=value
como dois comandos separados. Emite um erro sobre a segunda string. A atribuição permanece ineficaz.echo
eVAR=value
analisa essa unidade única de acordo com as regras apropriadas e a executa.Por último, mas não menos importante,
eval
pode ser um comando muito perigoso. Qualquer entrada em umeval
comando deve ser cuidadosamente verificada para evitar problemas de segurança.fonte
eval
não possui uma página de manual porque não é um comando externo separado, mas um shell interno, o que significa um comando interno e conhecido apenas pelo shell (bash
). A parte relevante dabash
página de manual diz:Além disso, a saída se
help eval
é:eval
é um comando poderoso e, se você pretende usá-lo, deve ter muito cuidado para evitar os possíveis riscos de segurança que o acompanham.fonte
A instrução eval diz ao shell para pegar os argumentos de eval como comando e executá-los na linha de comando. É útil em uma situação como abaixo:
No seu script, se você estiver definindo um comando em uma variável e, posteriormente, desejar usar esse comando, use eval:
fonte
ls | more
. Em outras palavras: O nome do comando único consistia em nove caracteres, incluindo os espaços e o símbolo de barra vertical .O que é eval?
eval é um comando shell que geralmente é implementado como um componente interno.
No POSIX, ele é listado como parte de "2.14. Utilitários embutidos especiais" na entrada "eval" .
O que significa builtin é:
O que isso faz?
Em termos simples: faz com que uma linha de entrada seja analisada duas vezes .
Como isso acontece?
O shell possui uma sequência de etapas a seguir para "processar" uma linha. Você pode olhar para esta imagem e perceber que eval é a única linha que sobe de volta à etapa 1, à esquerda. Na descrição do POSIX :
Na etapa 6, um built-in será executado.
Na etapa 6, eval faz com que a linha processada seja enviada de volta para a etapa 1.
É a única condição sob a qual a sequência de execução retorna.
Efeitos da análise duas vezes.
O primeiro.
E efeito mais importante para entender. É que uma consequência da primeira vez que uma linha está sujeita às sete passos shell mostrados acima, está citando . Na etapa 4 (expansões), também há uma sequência de etapas para executar todas as expansões , a última das quais é Remoção de cotação :
Portanto, sempre, há um nível de cotação removido.
Segundo.
Como conseqüência desse primeiro efeito, partes adicionais / diferentes da linha ficam expostas à análise de shell e a todas as outras etapas.
Exemplo.
Indirection.
Isso permite executar expansões indiretas:
Por quê? Porque no primeiro loop, o primeiro
$
é citado.Como tal, é ignorado para expansões pelo shell.
O próximo
$
com o nome a é expandido para produzir "b".Em seguida, um nível de citação é removido, tornando o primeiro
$
não citado.Fim do primeiro loop.
É então, no segundo loop, que a string
$b
é lida pelo shell.Então expandido para "c"
E dado como argumento para
echo
.Para "ver" o que o eval produzirá no primeiro loop (para ser avaliado novamente), use echo. Ou qualquer comando / script / programa que mostre claramente os argumentos:
Substitua eval por eco para "ver" o que está acontecendo:
Também é possível mostrar todas as "partes" de uma linha com:
Que, neste exemplo, é apenas um eco e uma variável, mas lembre-se de ajudar na avaliação de casos mais complexos.
Uma correção
Deve-se dizer que: há um erro no código acima, você vê?
Fácil: faltam algumas aspas.
Quão? você pode perguntar. Simples, vamos mudar as variáveis (não o código):
Veja os espaços que faltam?
Isso ocorre porque o valor interno
$b
foi dividido pelo shell.Se isso não o convencer, tente o seguinte:
Por quê?
Citações ausentes. Para fazê-lo funcionar corretamente (adicione aspas internas
"$a"
e externas\"
).Tente isto (é perfeitamente seguro):
Sobre o manual:
Não, não há uma página de manual independente para isso. A pesquisa de manual com
man -f eval
ou mesmoapropos eval
não mostra entrada.Está incluído no interior
man bash
. Como é qualquer embutido.Procure por "SHELL BUILTIN COMMANDS" e depois por "eval".
Uma maneira mais fácil de obter ajuda é: No bash, você pode fazer
help eval
para ver a ajuda do built-in.Por que eval é chamado de mal?
Porque está vinculando o texto ao código dinamicamente.
Em outras palavras: converte a lista de seus argumentos (e / ou expansões de tais argumentos) em uma linha executada. Se, por qualquer motivo, um argumento tiver sido definido por um invasor, você estará executando o código do invasor.
Ou ainda mais simples: com eval, você está dizendo a quem definiu o valor de um ou vários argumentos:
Isso é perigoso? Deve ser claro para todos que é.
A regra de segurança para eval deve ser:
Execute eval apenas nas variáveis às quais você deu valor.
Leia mais detalhes aqui .
fonte
eval
é uma característica das línguas mais interpretadas (TCL
,python
,ruby
...), não apenas conchas. É usado para avaliar o código dinamicamente.Em shells, é implementado como um comando embutido no shell.
Basicamente,
eval
pega uma string como argumento e avalia / interpreta o código nela. Em shells,eval
pode levar mais de um argumento, maseval
apenas concatena aqueles para formar a string a ser avaliada.É muito poderoso porque você pode construir código dinamicamente e executá-lo, algo que não pode ser feito em linguagens compiladas como C.
Gostar:
Mas também é perigoso, pois é importante higienizar as partes dinâmicas (fornecidas externamente) do que é passado
eval
pelo mesmo motivo que é interpretado como código do shell.Por exemplo, acima de se
$1
forevil-command; var
,eval
acabaria avaliando oevil-command; var=$varvalue
código do shell e o executariaevil-command
.A maldade de
eval
muitas vezes é exagerada.OK, é perigoso, mas pelo menos sabemos que é perigoso.
Um monte de outros comandos irá avaliar o código shell em seus argumentos, se não higienizado, como (dependendo do shell),
[
akatest
,export
,printf
, GNUsed
,awk
e, claro,sh
/bash
/perl
e todos os intérpretes ...Exemplos (aqui usando
uname
como osevil-command
e$a
como dados não autorizados fornecidos externamente):Aqueles
sed
,export
... comandos poderia ser considerado mais perigoso porque enquanto é óbvioeval "$var"
fará com que o conteúdo$var
a ser avaliado como código shell, não é tão óbvio comsed "s/foo/$var/"
ouexport "$var=value"
ou[ "$var" -gt 0 ]
. A perigosidade é a mesma, mas está oculta nesses outros comandos.fonte
sed
comoeval
está sendo passado uma string contida em uma variável, e para ambos, o conteúdo dessa string acaba sendo avaliado como código shell, entãosed
é tão perigoso quantoeval
, é o que estou dizendo.sed
está passando uma string contendouname
(uname ainda não foi executado) e, através da invocação desed
, o comando uname acaba sendo executado. Como para avaliação. Emsed 's/foo/$a/g'
, você não está transmitindo dados não autorizadossed
, não é disso que estamos falando aqui.Este exemplo pode lançar alguma luz:
Saída do script acima:
fonte
eval
. Você acredita que há algum aspecto fundamental e fundamental da funcionalidadeeval
que não é abordado nas respostas existentes? Nesse caso, explique -o e use o exemplo para ilustrar sua explicação. Por favor, não responda nos comentários; edite sua resposta para torná-la mais clara e completa.