En ash, dash y bash, cuando corro
$ echo ab$
vuelve
ab$
¿POSIX especifica este comportamiento o es solo una convención común en shells compatibles con POSIX? No pude encontrar nada en la página POSIX Shell Command Language que mencione este comportamiento.
$
Adquiere un significado especial si es el último carácter de una palabra?" No hay un significado especial único asignado a$
; se usa para introducir expansiones múltiples, pero distintas, como expansión de parámetros${...}
, sustitución de comandos$(...)
y expresiones aritméticas$((...))
. Algunos shells introducen contextos adicionales, comoksh
la variante de sustitución de comandosx=${ echo foo; echo bar;}
(que difiere del estándar$(...)
al no ejecutar los comandos en un subshell).ab$
, no hay caracteres a continuación$
, ya sea "seguido" por un carácter nulo en la cadena de entrada original o un espacio en un caso comoecho ab$ foo
; el espacio en blanco original sin comillas ha sido reconocido y descartado después del análisis.Respuestas:
$
no tiene un significado especial por sí mismo (tryecho $
), solo cuando se combina con otro personaje después de que y formando una expansión, por ejemplo,$var
(o${var}
),$(util)
,$((1+2))
.El
$
obtiene su "especial", que significa que la definición de una expansión en el estándar POSIX en la sección de reconocimiento simbólico :Entonces, si
$
no forma una expansión, entran en vigencia otras reglas de análisis:Eso cubre tu
ab$
cuerda.En el caso de un solitario
$
(la "nueva palabra" sería la$
sola):El significado de la palabra generada que contiene una
$
que no es una expansión estándar se define explícitamente como no especificado por POSIX.También tenga en cuenta que
$
es el último carácter en$$
, pero que también es la variable que contiene el PID del shell actual. Enbash
,!$
puede invocar una expansión del historial (el último argumento del comando anterior). Entonces, en general, no,$
no está exento de significado al final de una palabra sin comillas, pero al final de una palabra al menos no denota una expansión estándar.fuente
Dependiendo de la situación exacta, esto no está explícitamente especificado (por lo que las implementaciones pueden hacer lo que quieran) o se requiere que ocurra como usted observó. En su escenario exacto
echo ab$
, POSIX ordena la salida "ab $" que observó y no está sin especificar . Un resumen rápido de todos los diferentes casos está al final.Hay dos elementos: primero la tokenización en palabras, y luego la interpretación de esas palabras.
Tokenización
La tokenización POSIX requiere que un
$
que no sea el comienzo de una expansión de parámetro válida , sustitución de comando o sustitución aritmética se considere una parte literal delWORD
token que se está construyendo. Esto se debe a la regla 5 ("Si el carácter actual no está entre comillas$
o`
, el shell identificará el inicio de cualquier candidato para la expansión de parámetros, sustitución de comandos o expansión aritmética de sus secuencias de caracteres introductorias sin comillas:$
o${
,$(
o`
, y$((
, respectivamente" ) no se aplica, ya que ninguna de esas expansiones es viable allí. La expansión de parámetros requiere un nombre válido para aparecer allí, y un nombre vacío no es válido.Como esta regla no se aplica, continuamos siguiendo hasta encontrar una que sí lo haga. Los dos candidatos son el # 8 ("Si el carácter anterior era parte de una palabra, el carácter actual se agregará a esa palabra") y el # 10 ("El carácter actual se usa como el comienzo de una nueva palabra"). , que se aplican a
echo a$
yecho $
respectivamente.También hay un tercer caso de la forma
echo a$+b
que cae en la misma grieta, ya+
que no es el nombre de un parámetro especial. A este volveremos más adelante, ya que activa diferentes partes de las reglas.Por lo tanto, la especificación requiere que
$
se considere una parte de la palabra sintácticamente, y luego se pueda procesar más adelante.Expansión de palabras
Una vez que la entrada se ha analizado de esta manera, con la
$
palabra incluida, las expansiones de palabras se aplican a cada una de las palabras que se han leído. Cada palabra se procesa individualmente .Se especifica que :
"No especificado" es un término particular aquí que significa que
En su ejemplo,
echo ab$
el$
no va seguido de cualquier carácter , por lo que esta regla no se aplica y el resultado no especificado, no se invoca. Simplemente no hay expansión incitada por el$
, por lo que está literalmente presente e impreso.Donde podría aplicar es en nuestro tercer caso desde arriba:
echo a$+b
. Aquí$
es seguido por+
, que no es un número, parámetro especial (@
,*
,#
,?
,-
,$
,!
, o0
), inicio de una variable de nombre (o un guión bajo alfabético en la conjunto de caracteres portátil ), o uno de los soportes. En este caso, el comportamiento no está especificado: un shell conforme puede inventar un parámetro especial llamado+
expandir , y una aplicación conforme no debe asumir que el shell no lo hace . El shell también podría hacer cualquier otra cosa que quisiera, incluso informar un error.Por ejemplo, zsh, incluso en su modo POSIX, interpreta
$+b
como "es unb
conjunto variable " y sustituye 1 o 0 en su lugar. Del mismo modo tiene extensiones para~
y=
. Este es un comportamiento conforme.Otro lugar donde esto podría suceder es
echo "a$ b"
. Una vez más, el shell puede hacer lo que desee, y usted, como autor del script, debe escapar de$
si desea una salida literal. Si no lo hace, puede funcionar, pero no puede confiar en él. Esta es la letra absoluta de la especificación, pero no creo que este tipo de granularidad haya sido pensado o considerado.En resumen
echo ab$
: salida literal, completamente especificadaecho a$ b
: salida literal, completamente especificadaecho a$ b$
: salida literal, completamente especificadaecho a$b
: expansión del parámetrob
, completamente especificadaecho a$-b
: expansión de parámetro especial-
, completamente especificadoecho a$+b
: comportamiento no especificadoecho "a$ b"
: comportamiento no especificadoPara un
$
al final de una palabra, se le permite confiar en el comportamiento y debe tratarse literalmente y transmitirse alecho
comando como parte de su argumento. Ese es un requisito de conformidad en el shell.fuente
echo $
También sería literal y completamente especificado?echo "$"
yecho "a b$"
caer?