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.shy 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.shmodificado a unwccontenedor: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
@Qesta 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
printfcadena de formato" %q"y eliminar laseparatorvariable. 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á entrewithynewline, 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