Bash: eval e echo usam juntos

2

Esta é uma questão muito específica. Eu tenho um roteiro feito que, pelo que parece, eu poderia ter feito mais complicado do que o necessário em nome da eficiência. Isso é realmente eficiente? Eu não sei. É a maneira correta de escrever isso? Eu não sei.

É por isso que estou fazendo esta pergunta, quero saber se o código abaixo pode ser melhorado de como está escrito é a maneira de escrevê-lo. Se não fosse claro, eu sou um novato no bash, mas meu script completa seu propósito.

Este código está tentando definir as variáveis s$counter= s1, s2, s3, s4... em termos das variáveis definidas anteriormente s1$j e s2$j com j uma string que é um item de uma lista (todas definidas anteriormente).

counter=1 
for j in ${list[@]}
    do
            eval s$counter=$(eval "echo \$s1$j")
            eval s$((counter+1))=$(eval "echo \$s2$j")
            counter=$((counter+2))
    done

É confuso, mas nu comigo. O% internoeval, significando $(eval "echo \$s1$j") es significou retornar o valor de s1$j . O segundo eval , significando eval s$counter =... , destina-se a definir as variáveis s1, s2, s3, s4 ...

Portanto, um exemplo seria: digamos que o primeiro loop foor j=a then $(eval "echo \$s1$j") == $s1a , com o valor de s1a definido anteriormente no script, por exemplo, seja " s1a=10 ", para que quando o segundo eval é avaliado, temos o comando que indica " s1=10 ".

Funciona, mas algo poderia acontecer que tornaria isso uma possível ameaça à memória ou algo assim ?.

A mesma ideia com esta linha de código.

eval $(echo "sed -i '$(eval echo '17i$sed17line')' $file")

onde sed17line é o que eu quero adicionar na linha 17 de file . Depende do que eu quero usar o script, e é por isso que estou usando-o como uma variável e, portanto, por que estou usando uma combinação de echo e eval .

Mais uma vez, eu tentei tudo o que pude pensar que fazia sentido até que o resultado fosse o que eu queria.

Eu só quero ter certeza de que tudo está correto e se há uma maneira de melhorá-lo onde eu deveria procurar essa informação. Obrigado!

    
por M.O. 16.05.2018 / 20:24

1 resposta

1

É bom estar ciente de que há problemas com eval ( este e isso ) e echo ( aqui ). Você deve evitar eval , é fácil usar mal.

Mesmo que esses comandos sejam completamente seguros em seus casos particulares, sugiro que você solte eval . Seu código é realmente complicado por causa disso.

Seu primeiro exemplo fica muito mais limpo com matrizes. Isso funciona no GNU bash 4.4.12 no meu Debian:

# preparing variables
unset -v list s s1 s2
declare -a list=( foo 'X Y' bar baz )
declare -a s
declare -A s1=( [foo]='FOO 1' [bar]='BAR 2' [baz]='BAZ beep; eject /dev/sr0' )
declare -A s2=( [foo]='oof oof' [bar]='rab rab' [baz]='zab zab' [X Y]='9')

# your code rewritten, we don't even need a counter
for j in "${list[@]}"
  do
    s+=( "${s1[$j]}" "${s2[$j]}" )
  done

# checking contents of s
printf '%s\n' "${s[@]}"

Dica: pesquise "matrizes indexadas", "matrizes associativas" e seu uso em bash .

Observe que o elemento com espaço ( X Y ) não é nada especial para mim; mas isso quebraria seu código. Eu também posso ter BAZ beep; eject /dev/sr0 no meu s1 ; Eu desafio você a definir s1baz='BAZ beep; eject /dev/sr0' , ter baz na sua matriz list , executar seu código e ver o que acontece. Isto é o que o eval é capaz de fazer. Agora imagine que coloquei rm -rf ~/ em vez de eject … .

O segundo exemplo pode ser muito simplificado como:

sed -i "17i$sed17line" "$file"

Você parece ter algum preconceito em relação a eval + echo desde que criou uma engenhoca que as usa duas vezes quando nenhuma é necessária. Talvez seja porque suas variáveis nem sempre se expandem para seus valores quando você quer isso; Nesse caso, investigue a diferença entre aspas simples ( ' ) e aspas duplas ( " ) em bash .

Parabéns por ter dúvidas e fazer a pergunta.

    
por 16.05.2018 / 22:38

Tags