Perché la tilde (~) non si espande tra virgolette?


54

Secondo questa risposta e la mia comprensione, la tilde si espande nella home directory:

$ echo ~
/home/braiam

Ora, ogni volta che voglio che l'espansione della shell funzioni, cioè usando nomi di variabili simili $FOOe non rompere i caratteri imprevisti dovuti, tali spazi, ecc., Si dovrebbero usare le doppie virgolette ":

$ FOO="some string with spaces"
$ BAR="echo $FOO"
$ echo $BAR
echo some string with spaces

Perché questa espansione non funziona con la tilde?

$ echo ~/some/path
/home/braiam/some/path
$ echo "~/some/path"
~/some/path


3
Si noti inoltre che ciò ha l'incoerenza quando si fornisce un argomento di programma sulla riga di comando che sull'argomento di comando si --path ~/myfileespande ma --path=~/myfilenon lo fa.
Ángel,



Una variazione su questo tema è unix.stackexchange.com/questions/279565 .
JdeBP,

Risposte:


45

Il motivo, perché all'interno di doppie virgolette, tilde ~non ha alcun significato speciale, è trattata come letterale.

POSIX definisce le virgolette come:

Racchiudere i caratteri tra virgolette doppie ("") deve preservare il valore letterale di tutti i caratteri tra virgolette doppie, ad eccezione del segno di dollaro, backquote e barra rovesciata,

...

La domanda deve garantire che una doppia virgoletta sia preceduta da una barra rovesciata da includere tra virgolette doppie. Il parametro '@' ha un significato speciale tra virgolette doppie

Tranne che $, `, \e @, altri personaggi sono trattati come virgolette doppie all'interno letterali.


9
Nel qual caso suppongo che dovresti usare $HOME.
Seth,

11
Oppure non puoi semplicemente citare ~, ad esempiols -l ~/"My Documents"
Andrew Medico

Questo è molto intuitivo. Qual è il motivo per cui hanno scelto di farlo? (Questa risposta in realtà non fornisce il motivo, ma piuttosto indica solo lo standard, ma presumibilmente lo standard è stato scritto in quel modo per un motivo .)
iconoclasta il

1
@iconoclast se vuoi davvero un "perché sono stati implementati in questo modo" leggi invece la risposta di Stephane .
Braiam

2
Così, @iconoclast, perché è l'azzurro del cielo? :) :) :)
Jesse Chisholm,

32

L'espansione della tilde è definita da POSIX come:

Un "prefisso tilde" è costituito da un carattere <tilde> non quotato all'inizio di una parola, seguito da tutti i caratteri che precedono il primo <slash> non quotato nella parola o da tutti i caratteri nella parola se non è presente < tagliare>. In un compito, è possibile utilizzare più prefissi tilde: [...] seguendo il <equals-sign> del compito, seguendo qualsiasi <colon> non quotato, o entrambi. [...] Se nessuno dei caratteri nel prefisso tilde viene citato, i caratteri nel prefisso tilde che segue <tilde> vengono trattati come un possibile nome di accesso dal database utente. [...] Se il nome di accesso è nullo (ovvero, il prefisso tilde contiene solo la tilde), il prefisso tilde viene sostituito dal valore della variabile HOME. Se HOME non è impostato, i risultati non sono specificati. [...]

Quindi la risposta più breve è "perché è definita in questo modo": la citazione di uno qualsiasi dei caratteri nel prefisso, incluso il ~, elimina l'espansione.

Definisce inoltre l'espansione come sempre risultante in una sola parola, quindi la citazione non sarebbe necessaria:

Il nome del percorso risultante dall'espansione della tilde deve essere trattato come se fosse citato per evitare che venga alterato dalla divisione del campo e dall'espansione del nome del percorso.

Laddove parte del percorso richiede la quotazione, ma il resto è un prefisso tilde, è possibile combinare l'espansione tilde e la quotazione ordinaria in modo semplice:

$ cat ~/"file name with spaces"

Sul "perché" più ampio: dal momento che non è concepibile un uso per la suddivisione delle parole ~, questo dovrebbe essere il comportamento predefinito, piuttosto che richiederne la citazione. Poiché non è necessario citarlo, dare ~un significato speciale all'interno delle virgolette sarebbe una complicazione inutile. E, naturalmente, ragioni storiche significano che non potrebbe essere cambiato ora anche se fosse desiderabile.


Secondo questa guida bash , l'espansione della tilde avviene prima della separazione degli spazi bianchi. C'è un modo per eseguire in sicurezza un'espansione tilde, anche se la tua home directory contiene spazi bianchi? Di solito, ovviamente, faresti questo genere di cose con "".
Lucretiel,

L'espansione è una sola parola; vedere il secondo passaggio citato nella risposta.
Michael Homer,

23

~ ha origine nella shell C, molto prima che venisse aggiunta alla shell Korn e successivamente aggiunta alla specifica della shell POSIX.

Nel C-shell, ~c'era un operatore di globbing (espanso secondo la stessa routine di quello che si espandeva *.txtad esempio), così come il resto del globbing non veniva eseguito tra virgolette doppie.


11

Anche se questo non risponde al motivo per cui è stato progettato in questo modo, si utilizza $HOMEinvece se è necessario sostituire, poiché è essenzialmente ciò che ~fa.

$ echo "$HOME/some/path"
/home/braiam/some/path

6
questo non funziona con~otheruser
Johannes Kuhn,

2
Vero, ma potresti farlo: THEM = ~ otheruser quindi usa "$ THEM / some / path"
fonde il

1
La soluzione alternativa ~otherusermostra che è stata una cattiva idea trattare in modo ~diverso rispetto alle variabili e ad altre cose che sono espanse tra virgolette doppie.
iconoclasta il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.