¿Por qué Shell ignora las comillas en los argumentos que se le pasan a través de variables? [duplicar]

Resuelto Ben Wilhelm asked hace 12 años • 3 respuestas

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, 'helloserá 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 argumentStringvariables. 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?

Ben Wilhelm avatar Aug 27 '12 13:08 Ben Wilhelm
Aceptado

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 evales un lugar donde la discreción es mejor que la valentía. Si no tiene el control total de la cadena que se evalescribe (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.

Jonathan Leffler avatar Aug 27 '2012 06:08 Jonathan Leffler

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[@]}" .
nneonneo avatar Aug 27 '2012 06:08 nneonneo