¿Por qué Shell ignora las comillas en los argumentos que se le pasan a través de variables? [duplicar]
Estos funcionan como se anuncia:
grep -ir 'hello world' .
grep -ir hello\ world .
Estos no:
argumentString1="-ir 'hello world'"
argumentString2="-ir hello\\ world"
grep $argumentString1 .
grep $argumentString2 .
A pesar 'hello world'
de estar entre comillas en el segundo ejemplo, grep interpreta 'hello
(y hello\
) como un argumento y world'
(y world
) como otro, lo que significa que, en este caso, 'hello
será el patrón de búsqueda y world'
será la ruta de búsqueda.
Nuevamente, esto sólo sucede cuando los argumentos se expanden a partir de las argumentString
variables. grep interpreta correctamente 'hello world'
(y hello\ world
) como un argumento único en el primer ejemplo.
¿Alguien puede explicar por qué es esto? ¿Existe una forma adecuada de expandir una variable de cadena que preserve la sintaxis de cada carácter de modo que los comandos del shell la interpreten correctamente?
Por qué
Cuando la cadena se expande, se divide en palabras, pero no se vuelve a evaluar para encontrar caracteres especiales como comillas o signos de dólar o... Esta es la forma en que el shell se ha comportado "siempre", desde que el shell Bourne en 1978 más o menos.
Arreglar
En bash
, use una matriz para contener los argumentos:
argumentArray=(-ir 'hello world')
grep "${argumentArray[@]}" .
O, si es valiente/temerario, utilice eval
:
argumentString="-ir 'hello world'"
eval "grep $argumentString ."
Por otro lado, la discreción es a menudo la mejor parte del valor, y trabajar con eval
es un lugar donde la discreción es mejor que la valentía. Si no tiene el control total de la cadena que se eval
escribe (si hay alguna entrada del usuario en la cadena de comando que no ha sido validada rigurosamente), entonces se está exponiendo a problemas potencialmente graves.
Tenga en cuenta que la secuencia de expansiones para Bash se describe en Expansiones de Shell en el manual de GNU Bash. Tenga en cuenta en particular las secciones 3.5.3 Expansión de parámetros de Shell, 3.5.7 División de palabras y 3.5.9 Eliminación de comillas.
Cuando pones comillas en variables, simplemente se convierten en literales (ver http://mywiki.wooledge.org/BashFAQ/050 ; gracias @tripleee por señalar este enlace)
En su lugar, intenta usar una matriz para pasar tus argumentos:
argumentString=(-ir 'hello world')
grep "${argumentString[@]}" .