O 'eval' aplica o shell à parte de redirecionamento do seguinte comando?

2

Quando usar eval em um comando, eval aplica o shell duas vezes à parte de redirecionamento do comando?

Suponha que o nome do arquivo no redirecionamento contenha um espaço em branco, se eval aplicar todas as etapas da análise, expansões de shell e divisão de palavras e outras etapas mais de uma vez, o nome do arquivo será dividido em duas palavras durante a divisão. passo na segunda rodada.

O exemplo a seguir sugere que eval não aplica o shell duas vezes à parte de redirecionamento do comando a seguir, portanto, o nome do arquivo não é dividido em duas palavras?

$ filename="my file"
$ eval "cat" < "$filename"
hi
    
por Ben 23.11.2018 / 05:34

2 respostas

1

No exemplo que você fornece, a única coisa que eval está obtendo é cat , o redirecionamento está acontecendo fora de eval e o arquivo está sendo fornecido como stdin para o comando eval "cat" .

Uma variação é citar todo o comando, incluindo o redirecionamento, usando aspas simples:

$ eval 'cat < "$filename"'
hi

Agora, eval está obtendo a string inteira, incluindo o redirecionamento e o nome da variável, portanto, está fazendo uma expansão de variável e a cotação necessária para o nome do arquivo com espaços. Isso ainda funcionaria.

Outra opção é usar aspas duplas para a string:

$ eval "cat < '$filename'"
hi

Agora, a variável é expandida pelo shell, mas isso ainda funciona, pois as aspas dentro dela mantêm o nome do arquivo juntos. (Observe que isso quebraria se o nome do arquivo contivesse um apóstrofo).

O que não * funciona é isto:

$ eval "cat" "<" "$filename"

Isso é semelhante ao seu exemplo, mas com o < cotado, o redirecionamento não será executado pelo shell externo. eval reunirá os argumentos e o comando resultante será:

cat < my file

O que não funcionará como esperado, já que as aspas em torno de my file já desapareceram ...

    
por 23.11.2018 / 06:24
1

A maneira como o eval funciona é construindo os argumentos juntos como um comando shell a ser executado. Como sua variável filename é citada, ela não será submetida à divisão de palavras quando o comando this for construído para ser executado.

O mesmo pode não se aplicar a um caso do seu nome de arquivo com espaços e uma expansão sem aspas causará um erro. Por exemplo,

filname=my\ file
echo "dude" > my\ file
eval cat < $filename
bash: $filename: ambiguous redirect

Observe que a divisão de palavras foi feita aqui e cat recebe um nome de arquivo incorreto para redirecionamento de entrada, causando o erro.

Observe também que, se não for para o redirecionamento ao usar cat , se usado diretamente no arquivo, eval fará cat abrir dois arquivos nesse caso, ou seja,

eval cat $filename

se traduzirá em execução

cat my file

Por exemplo se você tiver o arquivo chamado file em seu diretório atual, ele exibirá seu conteúdo e mostrará o arquivo não presente para o arquivo chamado my no fluxo de erros.

filename=my\ file
echo "foo" > file

Estamos fazendo o arquivo my não estar presente

eval cat $filename 2>&1
cat: my: No such file or directory
foo
    
por 23.11.2018 / 06:13

Tags