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 del WORD
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$
y echo $
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 :
Si a un '$' sin comillas le sigue un carácter que no es uno de los siguientes:
- Un caracter numerico
- El nombre de uno de los parámetros especiales (ver Parámetros especiales )
- Un primer carácter válido de un nombre de variable
- A
<left-curly-bracket>
('{')
- UN
<left-parenthesis>
El resultado no está especificado.
"No especificado" es un término particular aquí que significa que
- Un shell conforme puede elegir cualquier comportamiento en este caso
- Una aplicación conforme no puede confiar en ningún comportamiento particular
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 ( @
, *
, #
, ?
, -
, $
, !
, o 0
), 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 un b
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 especificada
echo a$ b
: salida literal, completamente especificada
echo a$ b$
: salida literal, completamente especificada
echo a$b
: expansión del parámetro b
, completamente especificada
echo a$-b
: expansión de parámetro especial -
, completamente especificado
echo a$+b
: comportamiento no especificado
echo "a$ b"
: comportamiento no especificado
Para un $
al final de una palabra, se le permite confiar en el comportamiento y debe tratarse literalmente y transmitirse al echo
comando como parte de su argumento. Ese es un requisito de conformidad en el shell.
$
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).