¿Cómo puedo ejecutar una variable bash como comando exactamente sin comillas adicionales?

¿Cómo puedo ejecutar una variable bash como comando exactamente sin comillas adicionales?

Estoy intentando crear un script que deba guardar un comando para ejecutarlo como una cadena. La cadena en cuestión debe contener comillas y, al intentar ejecutarla, bash agrega comillas adicionales, lo que en algunos casos hace que el comando no se ejecute como se esperaba.

Aquí hay un guión de ejemplo. El comando exampleejecutado en este script de ejemplo obviamente no hace nada y simplemente dirá command not found, sin embargo, aún puede ejecutar el script y ver de qué estoy hablando porque agregué -xa la #!/bin/bashlínea para que se imprima el comando exacto que se está ejecutando. .

Ejemplo:

#!/bin/bash -x

#command typed explicitly
example -options "-i filename"

#command stored in string first
commandstring='example -options "-i filename"'
echo "running command: ${commandstring}"
${commandstring}

El resultado de ejecutar este script para mí es (ignorando los dos errores de "comando no encontrado"):

+ example -options '-i filename'
+ commandstring='example -options "-i filename"'
+ echo 'running command: example -options "-i filename"'
running command: example -options "-i filename"
+ example -options '"-i' 'filename"'

Entonces puedes ver que la primera línea, por supuesto, se ejecuta como se esperaba dando el parámetro de línea de comando:

-i filename

Sin embargo, aunque el echocomando imprime la cadena de una manera que también se ejecutaría perfectamente, cuando la cadena se coloca en la línea de comando cambia y el parámetro que se pasa se convierte en

'"-i' 'nombre de archivo"'

que contiene comillas adicionales, y esto está provocando que falle el comando real que estoy usando en mi script real.

hay alguna forma de prevenir esto?

Respuesta1

Si está utilizando bash, la forma más sencilla de guardar un comando exactamente es colocarlo en una matriz. Si el comando que desea ejecutar es:

example -options "-i filename"

puedes guardarlo en una variable de matriz con:

commandline=(example -options "-i filename")

Luego, puede ejecutar el comando guardado exactamente como está expandiendo @ la matriz entre comillas dobles:

"${commandline[@]}"

Lo clave que hay que saber aquí es que el shell trata los caracteres de comillas ( "'\) de manera diferente cuando se escriben directamente en la línea de comando que cuando los encuentra dentro de una expansión variable como en su ${commandstring}. En la línea de comandos, los caracteres de comillas tienen una función de comillas especial. Dentro de una expansión de parámetros, son simplemente caracteres normales no especiales. Por lo tanto, "-i filename"una sola palabra cuando se escribe en la línea de comando se analiza como -i filename, pero los mismos caracteres en una variable se expanden a las palabras "-iy filename".


BashPreguntas frecuentes 50cubre este tema con mucho mayor detalle.

información relacionada