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 foocontenga bar'bazdeberí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).

aliasy / osetbastante universalmentealias "varname=$varname" varnameovar=value setRespuestas:
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
printforden interna con el%qespecificador 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
printfincorporado es diferente de laprintfutilidad que viene incluida con la mayoría de los sistemas operativos tipo Unix. Si, por alguna razón, elprintfcomando 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\ndentro 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
printfsolució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
shdepó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 quxse puede utilizar comillas
bash
echo "${qux@Q}"zsh
echo "${(qq)qux}"# de una a cuatro q.fuente
grepconexportosetpueden interrumpir variables que contienen nuevas líneas incrustadas.