2012-02-28 17 views
10

Estoy intentando sustituir una variable de cadena, que contiene varias palabras entrecomilladas, como un parámetro de un comando.¿Cómo sustituir las cadenas de palabras múltiples citadas como argumentos?

Por lo tanto, dado el siguiente script de ejemplo (Nota del -x en el tinglado, lo que provoca que la salida se registra en stderr),

#!/bin/bash -x 

myArg="\"hello\" \"world\"" 
echo "string is:" $myArg 

exit 

Lo que nos da,

+ myArg='"hello" "world"' 
+ echo 'string is:' '"hello"' '"world"' 
string is: "hello" "world" 
+ exit 


La línea dos muestra lo que realmente se pasa al comando; bash ha agregado comillas simples a cada palabra en la cadena. Si en su lugar, por lo tanto, cito "$ myArg", ocurre lo mismo, pero para toda la cadena en lugar de cada palabra.

Imaginemos que en lugar de echo, estamos pasando la cadena a un programa donde algunos de los argumentos necesitan ser patrones citados, como "*" (que no debe ser expandido por el shell).

Para aclarar, no quiero que se agreguen las comillas simples durante la expansión. ¿Cómo podría lograr esto?

+0

¿Qué estás haciendo?A menos que estés haciendo algo asqueroso con 'eval' si la cadena que se pasa al programa contiene' "*" 'o' * 'no debería importar mucho. – Sorpigal

+0

Para cualquiera que esté confundido: tenga en cuenta que '-x' en el shebang hace que la salida se registre. – user123444555621

+0

@ Pumbaa80, de hecho, he agregado esa aclaración a la pregunta. –

Respuesta

13

no use comillas, utilizar una matriz (ver BashFAQ #050):

$ myArgs=("hello" "world" "multiword arg with * ?") 
+ myArgs=("hello" "world" "multiword arg with * ?") 
$ echo "${myArgs[@]}" 
+ echo hello world 'multiword arg with * ?' 
hello world multiword arg with * ? 

Si realmente tiene que ser en forma de cadenas entrecomilladas dentro de una cadena, tendrá que usar algo como eval "echo $myArg" (que puede causar algunos errores realmente desagradables, si no tiene cuidado) o analizarlo usted mismo (que va a ser difícil).

+0

Este enfoque Arrays funciona perfectamente, ¡muchas gracias! p. Cualquier impresión de una subshell es interpretada por el shell padre, por lo que cualquier declaración 'eval' parecía dar el mismo tipo de resultados malos. –

4

Si desea pasar un valor variable como un parámetro (el 99% de los casos en SO), sólo tiene un uso correcto quoting:

arg="foo bar" 
command "$arg" 

Si desea pasar varios argumentos, utilizar matrices:

args=("foo bar" "baz ban" bay) 
command "${args[@]}" 
+0

Según ha sido aclarado por @ gordon-davisson, las matrices fueron en verdad la respuesta, muchas gracias! –

0

No creo que esté haciendo lo que crees que está haciendo.

[~]$ myArg="\"hello\" \"world\"" 
[~]$ echo "string is:" $myArg 
string is: "hello" "world" 

veo sin comillas adicionales de cualquier tipo- echo tiene tres cadenas de argumentos.

[~]$ cargs(){ echo $#; } 
[~]$ cargs "string is:" $myArg 
3 

Bash ampliará la primera variable, por lo

cargs "string is:" $myArg 

se convierte en (aunque sin el literal backslashes- esta es la razón por cadena de escape es un PITA)

cargs "string is:" "\"hello\"" "\"world\"" 

Y la matriz args es:

0x00:string is:0 
0x0B:"hello"0 
0x13:"world"0 
0x1B:0 

Ahora, si agrega *, o expansión de ruta global en uno de ellos, Bash lo expandirá en este momento, a menos que lo escape, o use comillas simples en su comando literal.

[~]$ cargs "string is:" $myArg * 
19 
[~]$ cargs "string is:" $myArg "\*" 
4 
[~]$ cargs "string is:" $myArg '*' 
4 
+0

La salida * de Eco * imprime perfectamente las palabras entrecomilladas, pero los argumentos de entrada pasados ​​a eco (como se muestra en la línea dos de la salida de depuración en la pregunta) son citas simples-dobles ('"str"'), que desafortunadamente es una entrada sin sentido para la herramienta que estoy usando. –

Cuestiones relacionadas