Bash: eval y echo usan juntos

2

Esta es una pregunta realmente específica. Tengo un script que, por lo que parece, podría haberlo hecho más complicado de lo necesario en nombre de la eficiencia. ¿Es realmente eficiente? No lo sé. ¿Es la forma correcta de escribirlo? No lo sé.

Es por eso que estoy haciendo esta pregunta, quiero saber si el código a continuación se puede mejorar de cómo está escrito es la forma de escribirlo. Si no estaba claro, soy un novato en golpear pero mi guión completa su propósito.

Este código está tratando de definir las variables s$counter= s1, s2, s3, s4...en términos de las variables definidas previamente s1$jy s2$jcon juna cadena que es un elemento de una lista (todas definidas previamente).

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

Es confuso, pero desnudo conmigo. El evalsignificado interno significa $(eval "echo \$s1$j")devolver el valor de s1$j. El segundo eval, que significa evaluar, s$counter =...está destinado a definir las variabless1, s2, s3, s4 ...

Entonces, un ejemplo sería: digamos que para el primer bucle foor j=aentonces $(eval "echo \$s1$j") == $s1a, con el valor de s1a definido anteriormente en el script, por ejemplo, que sea " s1a=10", para que cuando evalse evalúe el segundo tengamos el comando que dice " s1=10".

Funciona, pero ¿podría pasar algo que haga de esto una posible amenaza de memoria o algo así?

La misma idea con esta línea de código.

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

donde sed17linees lo que quiero agregar en la línea 17 de file. Depende de para qué quiero usar el script, por eso lo estoy usando como variable y, por lo tanto, por qué estoy usando una combinación de echoy eval.

Una vez más, intenté todo lo que podía pensar que tenía sentido hasta que el resultado fue lo que quería.

Solo quiero asegurarme de que todo esté correcto y, si hay una manera de mejorarlo, debería buscar esa información. ¡Gracias!

mes
fuente
Bash tiene una construcción de matriz tldp.org/LDP/Bash-Beginners-Guide/html/sect_10_02.html Sin embargo, normalmente todo lo que necesita es un procesamiento de lista normalmente simple. Además, una evaluación por línea es suficiente. Eval solo trata la cadena expandida como si estuviera en el script.
T Nierath
¡Tienes razón! Solo una evaluación es necesaria. ¡Gracias!
MO

Respuestas:

1

Es bueno tener en cuenta que hay problemas con eval( esto y esto ) y echo( aquí ). Debe evitarlo eval, es fácil de usar mal.

Incluso si estos comandos son completamente seguros en sus casos particulares aquí, le aconsejo que abandone eval. Su código es realmente demasiado complicado debido a eso.


Su primer ejemplo se vuelve mucho más limpio con las matrices. Esto funciona en GNU bash 4.4.12 en mi 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[@]}"

Sugerencia: busque "matrices indexadas", "matrices asociativas" y su uso en bash.

Tenga en cuenta que el elemento con espacio ( X Y) no es nada especial para mí; pero rompería tu código También puedo tener BAZ beep; eject /dev/sr0en mi s1; Te reto a configurar s1baz='BAZ beep; eject /dev/sr0', tener bazen tu listmatriz, ejecutar tu código y ver qué pasa. Esto es lo que evales capaz de hacer. Ahora imagina que pongo en rm -rf ~/lugar de eject ….


El segundo ejemplo se puede simplificar enormemente como:

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

Parece que tiene algún sesgo hacia eval+ echoya que creó un artilugio que los usa dos veces cuando no se necesita ninguno. Tal vez sea porque sus variables no siempre se expanden a sus valores cuando lo desea; si es así, investigue la diferencia entre 'comillas simples ( ) y dobles ( ") en bash.

Felicitaciones por tener dudas y hacer la pregunta.

Kamil Maciorowski
fuente
¡Gracias! Creo que me diste demasiada información para procesar y tendré cuidado al tratar de obtenerlo todo. No diría que tengo un sesgo, diría que tengo una falta de conocimiento. Cuando busqué en Google específicamente lo que estaba tratando de hacer, todas las respuestas que encontré en foros como este eran usar evaly echo. Tal vez sea la forma en que estoy pensando que los pasos del código deberían ser los que me llevaron a esas respuestas, pero no obstante lo hicieron, funcionaron y tuvieron sentido para mí. Ahora estoy tratando de mejorar el código.
MO
El código tiene un uso muy específico, por lo que no me preocupa el uso incorrecto de eval, probablemente debería estarlo. ¿Diría que eval es portátil? Sin embargo, haré todo lo posible para comprender la forma en que me sugirió.
MO
Todo lo que ingenuamente utiliza la entrada del usuario y luego lo ejecuta (incluso cuando forma parte de una cadena más grande) tiene el potencial de ser explotado para ejecutar código arbitrario. Sin embargo, esto no debería importar demasiado, siempre que el script no se ejecute con permisos de root. Además, se debe usar un patrón común var=$(<prog>)que ejecute prog como un subproceso y asigne su salida a variable. No evalse necesita en este caso.
T Nierath