Por que o til (~) não expande as aspas duplas internas?

45

De acordo com esta resposta e meu próprio entendimento, o til se expande para o diretório inicial:

$ echo ~
/home/braiam

Agora, sempre que eu quiser que a expansão do shell funcione, i. e. usando nomes de variáveis como $FOO , e não quebre os caracteres inesperados, tais espaços, etc. deve-se usar aspas duplas " :

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

Por que essa expansão não funciona com o til?

$ echo ~/some/path
/home/braiam/some/path
$ echo "~/some/path"
~/some/path
    
por Braiam 24.08.2014 / 02:57

4 respostas

37

O motivo, porque dentro de aspas duplas, til ~ não tem significado especial, é tratado como literal.

POSIX define Double-Quotes como:

Enclosing characters in double-quotes ( "" ) shall preserve the literal value of all characters within the double-quotes, with the exception of the characters dollar sign, backquote, and backslash,

...

The application shall ensure that a double-quote is preceded by a backslash to be included within double-quotes. The parameter '@' has special meaning inside double-quotes

Exceto $ , ', \ e @ , outros caracteres são tratados como literal entre aspas duplas.

    
por 24.08.2014 / 07:09
29

Expansão de til é definida por POSIX como:

A "tilde-prefix" consists of an unquoted <tilde> character at the beginning of a word, followed by all of the characters preceding the first unquoted <slash> in the word, or all the characters in the word if there is no <slash>. In an assignment, multiple tilde-prefixes can be used: [...] following the <equals-sign> of the assignment, following any unquoted <colon>, or both. [...] If none of the characters in the tilde-prefix are quoted, the characters in the tilde-prefix following the <tilde> are treated as a possible login name from the user database. [...] If the login name is null (that is, the tilde-prefix contains only the tilde), the tilde-prefix is replaced by the value of the variable HOME. If HOME is unset, the results are unspecified. [...]

Portanto, a resposta mais curta é "porque é definida dessa maneira": citando qualquer um dos caracteres no prefixo, incluindo ~ , suprime a expansão.

Ele também define a expansão como sempre resultando em uma única palavra, então seria desnecessário citar:

The pathname resulting from tilde expansion shall be treated as if quoted to prevent it being altered by field splitting and pathname expansion.

Onde alguns dos caminhos exigem aspas, mas o resto é um prefixo til, você pode combinar diretamente a expansão do til e as cotações comuns:

$ cat ~/"file name with spaces"

No mais amplo "por que": como não há nenhum uso concebível para a divisão de palavras ~ , esse deve ser o comportamento padrão, em vez de exigir que seja citado. Porque não há necessidade de citá-lo, dar a ~ um significado especial dentro de citações seria uma complicação desnecessária. E, claro, razões históricas significam que não poderia ser mudado agora, mesmo que isso fosse desejável.

    
por 24.08.2014 / 03:18
20

~ é originado no C-shell, muito antes de ser adicionado ao shell Korn e posteriormente adicionado à especificação do shell POSIX.

No C-shell, ~ era um operador de globbing (expandido pela mesma rotina que o de expansão *.txt , por exemplo), assim como o resto do globbing não era executado entre aspas duplas.

    
por 24.08.2014 / 22:41
9

Embora isso não responda por que ele foi projetado dessa forma, você usa $HOME se precisar substituí-lo, já que é essencialmente o que ~ faz.

$ echo "$HOME/some/path"
/home/braiam/some/path
    
por 24.08.2014 / 11:49

Tags