3

Может кто-нибудь объяснить мне, почему это работает (перечисляя содержимое каталога, в имени которого есть пробел):

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

Не лучше ли это интерпретировать как:

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

Как например с:

ls "my" "dir"

а также

ls "my dir"

1 ответ1

6

Лучшее предположение на данный момент заключается в том, что вы спрашиваете:

Команда

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

довольно ужасный пример команды, которая содержит четыре двойных кавычки (").  Можно наивно ожидать, что вторая цитата будет соответствовать первой, а четвертая - третьей, например:

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

как, например, происходит с

    eat "afternoon snack" dinner "midnight snack"

Вместо этого он "работает" следующим образом:

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

Почему вложенные цитаты анализируются таким образом?

Этот абзац bash(1) может объяснить это:

Подстановка команд

                        ⋮
    … При использовании формы $(command) все символы в скобках составляют команду….

Я предполагаю, что это означает, что вы наблюдали, а именно, текст между $( и ) обрабатывается так, как если бы это была отдельная команда со своим собственным синтаксическим анализом / спариванием кавычек, независимо от синтаксических элементов вне скобок.  Я признаю, что если вы не ищете этого значения, это очень трудно интерпретировать.


Но ваш вопрос, как написано, не имеет смысла.  Все дело в особом значении (значениях) $ для оболочки.  Если мы изменили это на какой-то другой символ валюты,

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

тогда это будет рассматриваться как два слова:

        ret="£(ls "my
(с последующим)
                                    dir")"

потому что, если непустой, не специальный символ появляется непосредственно перед открывающей кавычкой или сразу после закрывающей кавычки, он включается в ту же строку, что и символы, заключенные в кавычки.  Например,

    cat Wal"*"mart

ищет файл с именем Wal*mart , а не файл с именем Wal , один с именем * , а другой с именем mart - Wal"*"mart эквивалентен Wal\*mart и "Wal*mart" .  Аналогично, следующий пример показывает четыре слова:

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

Я не знаю, где вы получили разбивку на три строки, которую вы показали в своем вопросе.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .