Dependendo da situação exata, isso é explicitamente não especificado (portanto, as implementações podem fazer o que quiserem) ou deve acontecer como você observou. No seu cenário exato echo ab$
, o POSIX determina a saída "ab $" que você observou e não é especificada . Um resumo rápido de todos os casos diferentes está no final.
Existem dois elementos: primeiro colocar token em palavras e depois interpretá-las.
Tokenização
A tokenização POSIX exige que uma $
que não seja o início de uma expansão de parâmetro válida , substituição de comando ou substituição aritmética seja considerada uma parte literal do WORD
token que está sendo construído. Isso ocorre porque a regra 5 ("Se o caractere atual é um não citado $
ou `
, o shell deve identificar o início de qualquer candidato para expansão de parâmetro, substituição de comando ou expansão aritmética de suas sequências de caracteres introdutórias não citadas: $
ou ${
, $(
ou `
, e $((
, respectivamente") ) não se aplica, pois nenhuma dessas expansões é viável lá. A expansão de parâmetros requer que um nome válido apareça lá e um nome vazio não é válido.
Como essa regra não se aplica, continuamos a seguir até encontrar uma que o aplique. Os dois candidatos são o número 8 ("Se o caractere anterior fazia parte de uma palavra, o caractere atual será anexado a essa palavra.") E o número 10 ("O caractere atual é usado como o início de uma nova palavra.") , que se aplicam a echo a$
e echo $
respectivamente.
Há também um terceiro caso do formulário echo a$+b
que se enquadra na mesma rachadura, já que +
não é o nome de um parâmetro especial. Voltaremos a este, pois desencadeia diferentes partes das regras.
A especificação exige, portanto, que $
seja considerada uma parte da palavra sintaticamente, e pode ser processada posteriormente posteriormente.
Expansão de palavras
Após a entrada ter sido analisada dessa maneira, com o $
incluído na palavra, expansões de palavras são aplicadas a cada uma das palavras que foram lidas. Cada palavra é processada individualmente .
É especificado que :
Se um '$' não citado for seguido por um caractere que não seja um dos seguintes:
- Um caractere numérico
- O nome de um dos parâmetros especiais (consulte Parâmetros especiais )
- Um primeiro caractere válido de um nome de variável
- A
<left-curly-bracket>
('{')
- UMA
<left-parenthesis>
o resultado não é especificado.
"Não especificado" é um termo específico aqui, significando que
- Um shell em conformidade pode escolher qualquer comportamento neste caso
- Um aplicativo em conformidade não pode confiar em nenhum comportamento específico
No seu exemplo, echo ab$
the $
não é seguido por nenhum caractere ; portanto, esta regra não se aplica e o resultado não especificado não é chamado. Simplesmente não há expansão incitada pelo $
, portanto está literalmente presente e impressa.
Onde ele iria aplicar está em nosso terceiro caso de cima: echo a$+b
. Aqui $
é seguido por +
, o que não é um número, parâmetro especial ( @
, *
, #
, ?
, -
, $
, !
, ou 0
), comece de uma variável nome (sublinhado ou um alfabética a partir do conjunto de caracteres portáteis ), ou um dos suportes. Nesse caso, o comportamento não é especificado: é permitido que+
um shell em conformidade invente um parâmetro especial chamado expansão , e um aplicativo em conformidade não deve assumir que o shell não o faça . O shell também poderia fazer qualquer outra coisa que gostasse, incluindo relatar um erro.
Por exemplo, zsh, inclusive em seu modo POSIX, interpreta $+b
como " b
conjunto de variáveis " e substitui 1 ou 0 em seu lugar. Da mesma forma, possui extensões para ~
e =
. Este é um comportamento conforme.
Outro lugar em que isso poderia acontecer é echo "a$ b"
. Novamente, o shell pode fazer o que quiser, e você, como autor do script, deve escapar do $
se desejar saída literal. Caso contrário, pode funcionar, mas você não pode confiar nela. Esta é a letra absoluta da especificação, mas não acho que esse tipo de granularidade tenha sido planejado ou considerado.
Em suma
echo ab$
: saída literal, totalmente especificado
echo a$ b
: saída literal, totalmente especificado
echo a$ b$
: saída literal, totalmente especificado
echo a$b
: expansão do parâmetro b
, totalmente especificado
echo a$-b
: expansão de parâmetro especial -
, totalmente especificado
echo a$+b
: comportamento não especificado
echo "a$ b"
: comportamento não especificado
No $
final de uma palavra, você tem permissão para confiar no comportamento e ele deve ser tratado literalmente e transmitido ao echo
comando como parte de seu argumento. Esse é um requisito de conformidade no shell.
$
ganha um significado especial se for o último caractere de uma palavra?" Não existe um único significado especial atribuído a$
; é usado para introduzir várias expansões, mas distintas, como expansão de parâmetro${...}
, substituição de comando$(...)
e expressões aritméticas$((...))
. Alguns shells introduzem contextos adicionais, comoksh
a variante de substituição de comandox=${ echo foo; echo bar;}
(que difere do padrão$(...)
por não executar os comandos em um subshell).