Quiero ejecutar un comando desde un script bash que tiene comillas simples y algunos otros comandos dentro de las comillas simples y una variable.
p.ej repo forall -c '....$variable'
En este formato, $
se escapa y la variable no se expande.
Intenté las siguientes variaciones pero fueron rechazadas:
repo forall -c '...."$variable" '
repo forall -c " '....$variable' "
" repo forall -c '....$variable' "
repo forall -c "'" ....$variable "'"
Si sustituyo el valor en lugar de la variable, el comando se ejecuta muy bien.
Por favor dime dónde me estoy equivocando.
repo forall -c ' ...before... '"$variable"' ...after...'
bash
Come comillas simples. O no estás dentrobash
, o las comillas simples no son parte delrepo
comando.Respuestas:
Dentro de las comillas simples todo se conserva literalmente, sin excepción.
Eso significa que debe cerrar las comillas, insertar algo y luego volver a ingresar.
La concatenación de palabras se realiza simplemente por yuxtaposición. Como puede verificar, cada una de las líneas anteriores es una sola palabra para el shell. Las comillas (comillas simples o dobles, según la situación) no aíslan las palabras. Solo se usan para deshabilitar la interpretación de varios caracteres especiales, como espacios en blanco
$
,;
... Para un buen tutorial sobre citas, vea la respuesta de Mark Reed. También relevante: ¿Qué caracteres se deben escapar en bash?No concatene cadenas interpretadas por un shell
Debe evitar absolutamente la creación de comandos de shell concatenando variables. Esta es una mala idea similar a la concatenación de fragmentos SQL (inyección SQL).
Por lo general, es posible tener marcadores de posición en el comando y proporcionar el comando junto con variables para que el destinatario pueda recibirlos de la lista de argumentos de invocación.
Por ejemplo, lo siguiente es muy inseguro. NO HAGAS ESTO
Si el contenido de
$myvar
no es confiable, aquí hay un exploit:En lugar de la invocación anterior, use argumentos posicionales. La siguiente invocación es mejor, no es explotable:
Tenga en cuenta el uso de marcas simples en la asignación de
script
, lo que significa que se toma literalmente, sin expansión variable o cualquier otra forma de interpretación.fuente
"some"thing' like'this
es todo una palabra para la concha. Las comillas no terminan nada en lo que respecta al análisis, y no hay forma de que un comando llamado por el shell indique qué se citó cómo.Al
repo
comando no le importa qué tipo de citas obtiene. Si necesita expansión de parámetros, use comillas dobles. Si eso significa que terminas teniendo que hacer una barra diagonal inversa de muchas cosas, usa comillas simples para la mayor parte, y luego sal de ellas y entra en dobles para la parte donde necesitas que ocurra la expansión.La explicación sigue, si está interesado.
Cuando ejecuta un comando desde el shell, lo que ese comando recibe como argumentos es una matriz de cadenas terminadas en cero. Esas cadenas pueden contener absolutamente cualquier carácter no nulo.
Pero cuando el shell construye ese conjunto de cadenas desde una línea de comando, interpreta algunos caracteres especialmente; Esto está diseñado para hacer que los comandos sean más fáciles (de hecho, posibles) de escribir. Por ejemplo, los espacios normalmente indican el límite entre cadenas en la matriz; por esa razón, los argumentos individuales a veces se llaman "palabras". Pero, sin embargo, un argumento puede tener espacios; solo necesita alguna forma de decirle al shell que es lo que quiere.
Puedes usar una barra invertida delante de cualquier personaje (incluido el espacio u otra barra invertida) para indicarle al shell que trate a ese personaje literalmente. Pero si bien puedes hacer algo como esto:
echo \"Thank\ you.\ \ That\'ll\ be\ \$4.96,\ please,\"\ said\ the\ cashier
... puede ser agotador. Entonces el shell ofrece una alternativa: comillas. Estos vienen en dos variedades principales.
Las comillas dobles se denominan "comillas de agrupación". Evitan que se expandan los comodines y los alias, pero principalmente son para incluir espacios en una palabra. Otras cosas como la expansión de parámetros y comandos (el tipo de cosas señaladas por a
$
) aún suceden. Y, por supuesto, si desea una comilla doble literal dentro de comillas dobles, debe hacer una barra diagonal inversa:echo "\"Thank you. That'll be \$4.96, please,\" said the cashier"
Las comillas simples son más draconianas. Todo entre ellos se toma completamente literalmente, incluidas las barras invertidas. No hay absolutamente ninguna manera de obtener una comilla simple literal dentro de comillas simples.
Afortunadamente, las comillas en el shell no son delimitadores de palabras ; por sí mismos, no terminan una palabra. Puede entrar y salir de comillas, incluso entre diferentes tipos de comillas, dentro de la misma palabra para obtener el resultado deseado:
echo '"Thank you. That'\''ll be $4.96, please," said the cashier'
Así que eso es más fácil: muchas menos barras invertidas, aunque la secuencia de comillas cerradas, comillas simples literales, comillas simples, comillas abiertas y simples requiere algo de tiempo para acostumbrarse.
Los shells modernos han agregado otro estilo de comillas no especificado por el estándar POSIX, en el cual la comilla simple principal está precedida por un signo de dólar. Las cadenas así citadas siguen convenciones similares a los literales de cadena en el lenguaje de programación ANSI C y, por lo tanto, a veces se llaman "cadenas ANSI" y el
$'
...'
par "citas ANSI". Dentro de tales cadenas, el consejo anterior sobre las barras invertidas literalmente ya no se aplica. En cambio, se vuelven especiales de nuevo: no solo puede incluir una comilla simple o una barra invertida literal al anteponer una barra invertida, sino que el shell también expande los escapes de caracteres ANSI C (como\n
para una nueva línea,\t
para tabulación y\xHH
para el personaje con código hexadecimalHH
) Sin embargo, de lo contrario, se comportan como cadenas entre comillas simples: no se realiza ninguna sustitución de parámetros o comandos:Lo importante a tener en cuenta es que la cadena única recibida como argumento del
echo
comando es exactamente la misma en todos estos ejemplos. Después de que el shell termine de analizar una línea de comando, no hay forma de que el comando que se ejecuta diga cómo se citó. Incluso si quisiera.fuente
$'string'
compatible el formato POSIX? Además, ¿hay un nombre para eso?$'string'
es una extensión que no es POSIX, a la que he visto referido como "cadenas ANSI"; He incorporado esos hechos en la respuesta. Tales cadenas funcionan en la mayoría de los shells compatibles con Bourne modernos: bash, dash, ksh (tanto AT&T como PD), y zsh todos los admiten.A continuación se muestra lo que funcionó para mí:
fuente
QUOTE
en una variable separada es completamente superfluo; Las comillas simples dentro de las comillas dobles son solo un carácter regular. (Además, no use mayúsculas para sus variables privadas).EDITAR: (Según los comentarios en cuestión :)
He estado investigando esto desde entonces. Tuve la suerte de tener un repositorio por ahí. Aún no me queda claro si necesita encerrar sus comandos entre comillas simples por la fuerza. Investigué la sintaxis del repositorio y no creo que sea necesario. Podrías usar comillas dobles alrededor de tu comando, y luego usar las comillas simples y dobles que necesites dentro, siempre que escapes las dobles.
fuente
solo usa printf
en vez de
use printf para reemplazar el token de la variable con la variable expandida.
Por ejemplo:
fuente
printf
en realidad no le compra nada aquí, y no citar la sustitución del comando causa nuevos problemas de cotización.Las variables pueden contener comillas simples.
fuente
"$myvar"
comillas dobles.¿Esto funciona para tí?
fuente