Tengo un script de envoltura que funciona y luego pasa los parámetros originales a otra herramienta:
#!/bin/bash
# ...
other_tool -a -b "$@"
Esto funciona bien, a menos que la "otra herramienta" se ejecute en una subshell:
#!/bin/bash
# ...
bash -c "other_tool -a -b $@"
Si llamo a mi script de envoltura así:
wrapper.sh -x "blah blup"
entonces, solo el primer argumento original (-x) se entrega a "other_tool". En realidad, no creo un subshell, pero paso los argumentos originales a un shell en un teléfono Android, lo que no debería hacer ninguna diferencia:
#!/bin/bash
# ...
adb sh -c "other_tool -a -b $@"
Ninguna de las soluciones funciona bien. Simplemente pase x / \ \ \ "b \" / aaaaa / \ 'xxx \ aaaa \' / zz \ "offf \" como parámetro y fallarán.
Aquí hay un contenedor simple que maneja cada caso. Tenga en cuenta cómo se escapa cada argumento dos veces.
fuente
Cambiar
$@
a$*
. Hice una pequeña prueba local y funciona en mi caso.Guardar como
test.sh
y hacerlo ejecutable daHay una sutil diferencia entre
$*
y$@
, como puede ver. Ver, por ejemplo, http://ss64.com/bash/syntax-parameters.htmlPara la pregunta de seguimiento en los comentarios: debe escapar, por ejemplo, el espacio en blanco "dos veces" para pasar una cadena con un separador como argumento combinado, por ejemplo, con
test.sh
modificado a unwc
contenedor:Esto funciona:
pero:
fuente
wrapper.sh -x "blah blup"
la subshell obtiene TRES parámetros (-x, bla, blup) en lugar de DOS (-x, "blah blup")"Blah\ blup"
. Pruébelo y vea si funciona.Está fallando porque está forzando una matriz (los parámetros posicionales) en una cadena.
"$@"
es mágico porque te da cada parámetro por separado como una cadena correctamente citada. Agregar texto adicional rompe la magia:"blah $@"
es solo una cadena.Esto puede acercarte:
Por supuesto, cualquier parámetro que contenga una comilla simple causará problemas.
fuente
Ok, más explicaciones:
fuente
Probé muchas soluciones diferentes, un buen recurso que incluye información de fondo y alternativas es, por ejemplo, BashFAQ / 096 en el Wiki de Greg (también conocido como GreyCat) . En total, encontré que los dos siguientes son los más legibles (de los que funcionan):
Desde Bash 4.4 (por lo que pude ver en las NOTICIAS ) es posible usar la expansión de parámetros de
@Q
esta manera:Tenga en cuenta que uso
$*
aquí en lugar de$@
porque desea"other_tool -a -b ${*@Q}"
ser una sola cadena en lugar de una cadena por argumento pasado.Si desea hacer lo mismo con una variable de matriz bash , necesitaría la sintaxis
${ARRAY[*]@Q}
(entre comillas).Si no tiene Bash 4.4 o posterior disponible o no está seguro, esta es mi solución preferida:
Tenga en cuenta que aquí se necesita para usar
"$@"
en lugar de$@
o"$*"
, o$*
porque no desea que la división de palabras dentro de los argumentos, por lo que las variantes sin citar no se puede utilizar, y desea que el número de argumentos que se conserva, por lo que"$*"
no se puede utilizar ya que se uniría Todos los argumentos a una sola cadena. La función luego devuelve todos los argumentos en una sola cadena.Si no le importa el espacio adicional delante del primer argumento, puede cambiar la
printf
cadena de formato" %q"
y eliminar laseparator
variable. O puede usar la respuesta de Gordon Davisson .Estas soluciones funcionan con todos los casos que se me ocurrieron, especialmente:
escapeBashArgs
→ nadaescapeBashArgs "" ""
→'' ''
escapeBashArgs " " " "
→' ' ' '
o\ \ \ \ \
( el último espacio lo ocupa el renderizador de este sitio )escapeBashArgs "a b" c\ d "arg with newline"
→'a b' 'c d' $'arg with\nnewline'
oa\ \ \ \ \ \ b c\ d $'arg with\nnewline'
( la línea nueva está entrewith
ynewline
, en otras posiciones, se debe al ajuste de línea en este sitio )escapeBashArgs '$"'\''({:})'
→'$"'\''({:})'
o\$\"\'\(\{:\}\)
escapeBashArgs x/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
→'x/ "b"/aaaaa/'\''xxx yyyy'\''/zz"offf"'
ox/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
(Probado con GNU bash 5.0.3 (1) -release.)
fuente
fuente