Aspas de Bash sem escape na substituição de comando

3

Alguém pode me explicar por que isso está funcionando (listando o conteúdo de um diretório que tem um espaço em branco em seu nome):

ret="$(ls "my dir")"

Não deve ser interpretado como:

ret="$(ls "
my dir
")"

Como por exemplo com:

ls "my" "dir"

e

ls "my dir"
    
por user2279268 04.05.2015 / 23:19

1 resposta

6

O melhor palpite até agora parece ser que você está perguntando:

The command

    ret="$(ls "my dir")"

is a pretty terrible example of a command that contains four double-quote (") marks.  One might naïvely expect that the second quote would match the first one, and the fourth would match the third, like this:

    ret="$(ls "my dir")"
        ↑-----↑      ↑-↑

as, for example, happens with

    eat "afternoon snack" dinner "midnight snack"

Instead, it “works”, as follows:

    ret="$(ls "my dir")"
        ↑     ↑------↑ ↑
        ↑--------------↑

Why are the nested quotes parsed that way?

Este parágrafo da bash (1) pode explicar:

Command Substitution

                        ⋮
    …  When using the $(command) form, all characters between the parentheses make up the command ….

Eu acho que isso significa o que você observou, ou seja, o texto entre o $( e o ) é tratado como se fosse um comando separado, com sua própria análise / pareamento de citações, independente de elementos sintáticos fora dos parênteses. Eu admito que, se você não está procurando por esse significado, é muito difícil de interpretar.

Mas sua pergunta, conforme escrita, não faz sentido. A coisa toda depende do (s) significado (s) muito especial (s) de $ para o shell. Se mudarmos isso para algum outro símbolo monetário,

    ret="£(ls "my dir")"

então seria tratado como duas palavras:

ret="£(ls "my
(seguido por)
dir")"

porque, se um caractere não-especial, não em branco, aparecer imediatamente antes de uma cotação de abertura ou imediatamente após uma cotação de fechamento, está incluído na mesma string que os caracteres entre aspas. Por exemplo,

    cat Wal"*"mart

procura um arquivo chamado Wal*mart , não é um arquivo chamado Wal , um chamado * e um chamado mart - Wal"*"mart é equivalente a Wal\*mart e "Wal*mart" . Da mesma forma, o exemplo a seguir mostra quatro palavras:

    one" "two  buckle" my "shoe  /don\'t/be/a/" "/cadet  sqrt"(2)"
    ↑-------↑  ↑--------------↑  ↑--------------------↑  ↑-------↑

Eu não sei onde você conseguiu o desarranjo de três linhas que você mostrou em sua pergunta.

    
por 05.05.2015 / 02:45