El echo
comando no incluye el texto completo que le doy. Por ejemplo, si lo hago:
$ echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` '
Produce:
echo PARAM=` grep $ARG /var/tmp/setfile | awk {print } `
Las comillas simples ( '
) que tenía en mi comando echo no están incluidas. Si cambio a comillas dobles:
$ echo " echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` "
echo
¡no produce nada en absoluto! ¿Por qué deja de lado las comillas simples en el primer ejemplo y no muestra nada en el segundo? ¿Cómo consigo que emita exactamente lo que escribí?
Respuestas:
Su shell está interpretando las citas, ambas
'
y"
, incluso antes de que lleguenecho
. Generalmente pongo comillas dobles alrededor de mi argumento para hacer eco, incluso si son innecesarias; por ejemplo:Entonces, en su primer ejemplo, si desea incluir comillas literales en su salida, es necesario que escapen:
O ya deben usarse dentro de un argumento citado (pero no puede ser el mismo tipo de cita, o tendrá que escapar de todos modos):
En su segundo ejemplo, está ejecutando una sustitución de comando en el medio de la cadena:
Las cosas que comienzan
$
también se manejan especialmente por el shell: las trata como variables y las reemplaza por sus valores. Como lo más probable es que ninguna de esas variables esté configurada en su shell, en realidad solo se ejecutaComo
grep
solo ve un argumento, asume que ese argumento es el patrón que está buscando, y que el lugar desde el que debe leer los datos es stdin, por lo que bloquea la espera de entrada. Es por eso que su segundo comando parece simplemente colgarse.Esto no sucederá si cita el argumento con comillas simples (es por eso que su primer ejemplo casi funcionó), por lo que esta es una forma de obtener el resultado que desea:
También puede ponerlo entre comillas dobles, pero luego necesitará escapar de la
$
s para que el shell no los resuelva como variables, y los backticks para que el shell no ejecute la sustitución del comando de inmediato:fuente
No voy a entrar en muchos detalles sobre por qué sus intentos se comportan de la manera en que lo hacen, porque la respuesta de Michael Mrozek cubre esto bien. En pocas palabras, todo lo que entre comillas simples (
'…'
) se interpreta literalmente (y en particular, la primera'
marca el final de la cadena literal), mientras que`
y$
conservan su significado especial entre"…"
.No hay comillas dentro de comillas simples, por lo que no puede poner una comilla simple dentro de una cadena entre comillas simples. Sin embargo, hay un idioma que se ve así:
Esto se imprime
foo'bar
, porque el argumento deecho
está hecho de la cadena de tres caracteres entre comillas simplesfoo
, concatenado con el carácter único'
(obtenido al proteger el carácter'
de su significado especial a través del precedente\
), concatenado con la cadena de tres caracteres entre comillas simplesbar
. Entonces, aunque eso no es exactamente lo que sucede detrás de escena, se puede considerar'\''
como una forma de incluir una comilla simple dentro de una cadena entre comillas simples.Si desea imprimir cadenas complejas de varias líneas, una mejor herramienta es el documento aquí . Un documento aquí consta de los dos caracteres
<<
seguidos de un marcador como<<EOF
, luego, algunas líneas de texto, luego el marcador final solo en su línea. Si el marcador se cita de alguna manera ('EOF'
oo"EOF"
o\EOF
'E "" OF' o ...), entonces el texto se interpreta literalmente (como dentro de comillas simples, excepto que incluso'
es un carácter ordinario). Si el marcador no se cita en absoluto, entonces el texto se interpreta como una cadena entre comillas dobles,$\`
conservando su estado especial (pero las"
líneas nuevas se interpretan literalmente).fuente
De acuerdo, esto funcionará: -
Probándolo aquí: -
fuente
La sugerencia de Gilles de usar un documento aquí es realmente agradable, e incluso funciona dentro de lenguajes de script como Perl. Como un ejemplo específico basado en su respuesta al problema del OP,
Por supuesto, este ejemplo es un poco artificial, pero he encontrado que es una técnica útil para, por ejemplo, enviar sentencias SQL a
psql
(en lugar decat
).(Tenga en cuenta que cualquier carácter no alfanumérico que no sea un espacio se puede usar en lugar de la
#
construcción de citas genéricas anterior, pero el hash parece destacarse bien para este ejemplo, y no se trata como un comentario).fuente
Tomemos tu comando
y primero se divide en palabras, usando espacios en blanco sin comillas como delimitador:
A continuación, hacemos la expansión de parámetros: expandir
$…
pero no dentro'…'
. Como$2
está vacío (a menos que lo establezca a través de, pset -- …
. Ej. ), Será reemplazado por una cadena vacía.Luego, elimine las cotizaciones.
Estos argumentos se pasan a echo, que los imprimirá uno tras otro, separados por un solo espacio.
Espero que esta instrucción paso a paso aclare el comportamiento observado. Para evitar el problema, evite las comillas simples como esta:
Esto finalizará la cadena de comillas simples, luego agregará una comilla simple (escapado) a la palabra, luego comenzará una nueva cadena de comillas simples, todo sin separar la palabra.
fuente