Em cinzas, traço e festança, quando corro
$ echo ab$
retorna
ab$
Esse comportamento é especificado pelo POSIX ou é apenas uma convenção comum em shells compatíveis com POSIX? Não consegui encontrar nada na página Linguagem de Comando do Shell POSIX que mencione esse comportamento.
$
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).ab$
, não há caracteres a seguir$
, se foi "seguido" por um caractere nulo na cadeia de entrada original ou por um espaço em um caso comoecho ab$ foo
; o espaço em branco não citado original foi reconhecido e descartado após a análise.Respostas:
$
não tem um significado especial, por si só (TRYecho $
), apenas quando combinado com outro carácter depois e formando uma expansão, por exemplo$var
(ou${var}
),$(util)
,$((1+2))
.O
$
recebe seu significado "especial" como definir uma expansão no padrão POSIX na seção Reconhecimento de token :Portanto, se
$
não formar uma expansão, outras regras de análise entrarão em vigor:Isso cobre sua
ab$
corda.No caso de um solitário
$
(a "nova palavra" seria a$
mesma):O significado da palavra gerada que contém uma
$
que não é uma expansão padrão é explicitamente definida como não especificada pelo POSIX.Observe também que esse
$
é o último caractere$$
, mas também é a variável que mantém o PID do shell atual. Embash
,!$
pode invocar uma expansão do histórico (o último argumento do comando anterior). Portanto, em geral, não,$
não deixa de ter significado no final de uma palavra não citada, mas no final de uma palavra pelo menos não indica uma expansão padrão.fonte
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 doWORD
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$
eecho $
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 :
"Não especificado" é um termo específico aqui, significando que
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 (@
,*
,#
,?
,-
,$
,!
, ou0
), 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 especificadoecho a$ b
: saída literal, totalmente especificadoecho a$ b$
: saída literal, totalmente especificadoecho a$b
: expansão do parâmetrob
, totalmente especificadoecho a$-b
: expansão de parâmetro especial-
, totalmente especificadoecho a$+b
: comportamento não especificadoecho "a$ b"
: comportamento não especificadoNo
$
final de uma palavra, você tem permissão para confiar no comportamento e ele deve ser tratado literalmente e transmitido aoecho
comando como parte de seu argumento. Esse é um requisito de conformidade no shell.fonte
echo $
Também seria literal e totalmente especificado?echo "$"
eecho "a b$"
caem?