Cytaty Bash nie zostały zmienione podczas podstawiania poleceń

3

Czy ktoś może mi wyjaśnić, dlaczego to działa (wyświetlając zawartość katalogu, który ma w nazwie białe znaki):

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

Czy raczej nie powinno to być interpretowane jako:

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

Na przykład z:

ls "my" "dir"

i

ls "my dir"
user2279268
źródło
Pytam, dlaczego działa ret = "$ (ls" mój dir ")".
user2279268
Mogę tylko zgadywać, że bash jest na tyle „inteligentny”, by zobaczyć, że a "$(" byłby błąd składniowy ( $ wewnątrz " jest oceniany) i próbuje znaleźć inne dopasowanie, które umożliwia zagnieżdżenie " w tym przypadku.
Slizzered

Odpowiedzi:

6

Jak na razie wydaje się, że pytasz:

Komenda

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

to dość okropny przykład polecenia   który zawiera cztery podwójne cytaty ( " ) znaki.   Można naiwnie oczekiwać, że drugi cytat będzie pasował do pierwszego,   a czwarty pasowałby do trzeciego, jak ten:

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

jak na przykład dzieje się z

    eat "afternoon snack" dinner "midnight snack"

Zamiast tego „działa” w następujący sposób:

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

Dlaczego zagnieżdżone cytaty są analizowane w ten sposób?

Ten akapit bash (1) może to wyjaśnić:

Zastępowanie poleceń


    … Podczas korzystania z $( dowództwo ) Formularz,   wszystkie znaki między nawiasami tworzą polecenie….

Myślę, że to oznacza to, co zaobserwowałeś, a mianowicie, tekst między $( i ) jest traktowany jakby to było osobne polecenie, z własnym parsowaniem / parowaniem cytatów, niezależny od elementów składniowych poza nawiasami. Przyznaję, że jeśli nie szukasz tego znaczenia, bardzo trudno to zinterpretować.


Ale twoje pytanie, jak napisano, nie ma sensu. Cała sprawa zależy od bardzo szczególnego znaczenia $ do skorupy. Jeśli zmienimy to na inny symbol waluty,

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

to byłoby traktowane jako dwa słowa:

ret="£(ls "my
(śledzony przez)
dir")"

ponieważ, jeśli pojawi się nie pusty, znak inny niż specjalny bezpośrednio przed kwotą otwarcia lub bezpośrednio po wycenie zamknięcia, jest zawarty w tym samym ciągu, co znaki zawarte w cudzysłowie. Na przykład,

    cat Wal"*"mart

szuka pliku o nazwie Wal*mart, nie plik o nazwie Wal, jeden nazywany *i jeden wezwany mart - Wal"*"mart jest równa Wal\*mart i "Wal*mart". Podobnie poniższy przykład pokazuje cztery słowa:

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

Nie wiem, skąd masz awarię trzech linii które pokazałeś w swoim pytaniu.

G-Man
źródło
Tak bym się spodziewał, że się zachowa.
user2279268