A seconda della situazione esatta, questo è esplicitamente non specificato (quindi le implementazioni possono fare come vogliono) o è necessario che accada come hai osservato. Nel tuo esatto scenario echo ab$
, POSIX impone l'output "ab $" che hai osservato e non è specificato . Alla fine è disponibile un breve riepilogo di tutti i diversi casi.
Ci sono due elementi: prima il tokenismo in parole e poi l'interpretazione di quelle parole.
tokenizzazione
La tokenizzazione POSIX richiede che a $
che non sia l'inizio di una valida espansione di parametro , sostituzione di comando o sostituzione aritmetica sia considerata una parte letterale del WORD
token in costruzione. Questo perché la regola 5 ("Se il carattere corrente non è citato $
o `
, la shell deve identificare l'inizio di qualsiasi candidato per l'espansione dei parametri, la sostituzione dei comandi o l'espansione aritmetica dalle loro sequenze introduttive di caratteri non quotati: $
oppure ${
, $(
o `
, e $((
, rispettivamente" ) non si applica, in quanto nessuna di tali espansioni è praticabile lì. L'espansione dei parametri richiede la visualizzazione di un nome valido e un nome vuoto non è valido.
Dal momento che questa regola non è stata applicata, continuiamo a seguirla fino a quando non ne troviamo una. I due candidati sono # 8 ("Se il carattere precedente faceva parte di una parola, il carattere corrente deve essere aggiunto a quella parola.") E # 10 ("Il carattere corrente viene utilizzato come inizio di una nuova parola.") , che si applicano a echo a$
e echo $
rispettivamente.
C'è anche un terzo caso della forma echo a$+b
che rientra nella stessa crack, poiché +
non è il nome di un parametro speciale. Questo torneremo più tardi, poiché innesca diverse parti delle regole.
La specifica richiede quindi che $
venga considerata sintatticamente una parte della parola, e può quindi essere ulteriormente elaborata in seguito.
Espansione delle parole
Dopo che l'analisi è stata analizzata in questo modo, con l'inserimento $
nella parola, le espansioni di parole vengono applicate a ciascuna delle parole che sono state lette. Ogni parola viene elaborata singolarmente .
Si specifica che :
Se un '$' non quotato è seguito da un carattere che non è uno dei seguenti:
- Un carattere numerico
- Il nome di uno dei parametri speciali (vedere Parametri speciali )
- Un primo carattere valido di un nome variabile
- A
<left-curly-bracket>
('{')
- UN
<left-parenthesis>
il risultato non è specificato.
"Non specificato" è un termine particolare qui che significa che
- Una shell conforme può scegliere qualsiasi comportamento in questo caso
- Un conforme applicazione non può contare su un particolare comportamento
Nel tuo esempio, echo ab$
il $
non è seguito da alcun carattere , quindi questa regola non si applica e il risultato non specificato non viene richiamato. Semplicemente non vi è alcuna espansione incitata da $
, quindi è letteralmente presente e stampata.
Dove sarebbe applicabile è nel nostro terzo caso dall'alto: echo a$+b
. Qui $
è seguito da +
, il che non è un numero, parametro speciale ( @
, *
, #
, ?
, -
, $
, !
, o 0
), avviare di una variabile nome (sottolineatura o un alfabetica dal set di caratteri portatile ), o di una delle staffe. In questo caso, il comportamento non è specificato: una shell conforme è autorizzata a inventare un parametro speciale chiamato +
per espandere , e un'applicazione conforme non dovrebbe supporre che la shell non lo faccia . La shell potrebbe fare anche qualcos'altro che gli piace, inclusa la segnalazione di un errore.
Ad esempio, zsh, incluso nella sua modalità POSIX, interpreta $+b
come "è b
impostato variabile " e sostituisce 1 o 0 al suo posto. Allo stesso modo ha estensioni per ~
e =
. Questo è un comportamento conforme.
Un altro posto in cui ciò potrebbe accadere è echo "a$ b"
. Ancora una volta, la shell è autorizzata a fare ciò che desidera e tu, come autore dello script, dovresti sfuggire $
se vuoi un output letterale. In caso contrario, potrebbe funzionare, ma non puoi fare affidamento su di esso. Questa è la lettera assoluta del disciplinare, ma non credo che questo tipo di granularità sia stato inteso o considerato.
In sintesi
echo ab$
: output letterale, completamente specificato
echo a$ b
: output letterale, completamente specificato
echo a$ b$
: output letterale, completamente specificato
echo a$b
: espansione del parametro b
, completamente specificata
echo a$-b
: espansione del parametro speciale -
, completamente specificato
echo a$+b
: comportamento non specificato
echo "a$ b"
: comportamento non specificato
Per una $
alla fine di una parola, si è permesso di fare affidamento sul comportamento e deve essere trattato in senso letterale e passato al echo
comando come parte della sua tesi. Questo è un requisito di conformità sulla shell.
$
guadagnare un significato speciale se è l'ultimo carattere in una parola?" Non esiste un singolo significato speciale assegnato a$
; è usato per introdurre espansioni multiple, ma distinte, come l'espansione dei parametri${...}
, la sostituzione dei comandi$(...)
e le espressioni aritmetiche$((...))
. Alcune shell introducono contesti aggiuntivi, comeksh
la variante di sostituzione dei comandix=${ echo foo; echo bar;}
(che differisce dallo standard$(...)
non eseguendo i comandi in una subshell).