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 WORDtoken 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$+bque 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 $+bcomo " bconjunto 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 echocomando 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, comoksha variante de substituição de comandox=${ echo foo; echo bar;}(que difere do padrão$(...)por não executar os comandos em um subshell).