Esta pregunta no se trata de cómo escribir un literal de cadena con escape correcto. No pude encontrar ninguna pregunta relacionada que no se trata de cómo escapar de las variables para el consumo directo dentro de un script o por otros programas.
Mi objetivo es habilitar un script para generar otros scripts. Esto se debe a que las tareas en los scripts generados se ejecutarán en cualquier lugar de 0 a n veces en otra máquina, y los datos a partir de los cuales se generan pueden cambiar antes de ejecutarse (nuevamente), por lo que realizar las operaciones directamente, a través de una red no trabajo.
Dada una variable conocida que puede contener caracteres especiales como comillas simples, necesito escribirla como un literal de cadena completamente escapado, por ejemplo, una variable que foo
contenga bar'baz
debería aparecer en el script generado como:
qux='bar'\''baz'
que se escribiría agregando "qux=$foo_esc"
a las otras líneas del guión. Lo hice usando Perl así:
foo_esc="'`perl -pe 's/('\'')/\\1\\\\\\1\\1/g' <<<"$foo"`'"
Pero esto parece una exageración.
No he tenido éxito en hacerlo solo con bash. He intentado muchas variaciones de estos:
foo_esc="'${file//\'/\'\\\'\'}'"
foo_esc="'${file//\'/'\\''}'"
pero aparecen barras diagonales adicionales en la salida (cuando lo hago echo "$foo"
), o causan un error de sintaxis (esperando una entrada adicional si se realiza desde el shell).
alias
y / oset
bastante universalmentealias "varname=$varname" varname
ovar=value set
Respuestas:
Bash tiene una opción de expansión de parámetros para exactamente este caso :
Entonces en este caso:
Esto es compatible con Bash 4.4 y versiones posteriores. También hay varias opciones para otras formas de expansión y para generar específicamente declaraciones de asignación completas (
@A
).fuente
bad substitution
."${foo:q}"
."${foo@Q}"
¡trabajos!Bash proporciona una
printf
orden interna con el%q
especificador de formato, que realiza shell de escape para que, incluso en (<4.0) versiones anteriores de Bash:Este truco también se puede usar para devolver matrices de datos de una función:
Tenga en cuenta que el Bash
printf
incorporado es diferente de laprintf
utilidad que viene incluida con la mayoría de los sistemas operativos tipo Unix. Si, por alguna razón, elprintf
comando invoca la utilidad en lugar de la integrada, siempre puede ejecutarlabuiltin printf
.fuente
'Ne'\''er do well'
, etc., es decir, citas incluidas en la salida.[[ 'Ne'\''er do well' == Ne\'er\ do\ well ]] && echo 'equivalent!'
se hará ecoequivalent!
'hello'
da como resultado un valor incorrecto''\''hello''
, que tiene una cadena vacía inicial innecesaria (las dos primeras comillas simples) y una comilla simple final inapropiada.$'escape-these-chars'
es la característica de comillas ANSI-C de Bash que hace que se escapen todos los caracteres dentro de la cadena especificada. Por lo tanto, para crear fácilmente un literal de cadena que contenga una nueva línea dentro del nombre de archivo (por ejemplo$'first-line\nsecond-line')
, usar\n
dentro de esta construcción.)Supongo que no hice RTFM. Se puede hacer así:
Luego
echo "$foo_esc"
da lo esperado'bar'\''baz'
Cómo lo estoy usando realmente es con una función:
Modificando esto para usar la
printf
solución integrada de Dejay:fuente
Hay varias soluciones para citar un valor var:
alias
En la mayoría de los shells (donde está disponible el alias) (excepto csh, tcsh y probablemente otros como csh):
Sí, esto funciona en muchos
sh
depósitos similares a guiones o cenizas.establecer
también en la mayoría de conchas (de nuevo, no CSH):
composición tipográfica
en algunos shells (ksh, bash y zsh al menos):
exportar
primero hacer:
Luego use:
ksh
export -p | grep 'qux='
bashexport -p | grep 'qux='
zsh
export -p qux
se puede utilizar comillas
bash
echo "${qux@Q}"
zsh
echo "${(qq)qux}"
# de una a cuatro q.fuente
grep
conexport
oset
pueden interrumpir variables que contienen nuevas líneas incrustadas.