Niecytowana zmienna (jak w $var) lub podstawienie polecenia (jak w $(cmd)lub `cmd`) to operator split + glob w powłokach podobnych do Bourne'a.
Oznacza to, że ich zawartość jest podzielona zgodnie z bieżącą wartością $IFSzmiennej specjalnej (która domyślnie zawiera znaki spacji, tabulacji i nowego wiersza)
A następnie każde słowo powstałe w wyniku tego podziału podlega generowaniu nazw plików (zwanych także globowaniem lub rozszerzaniem nazw plików ), to znaczy są one uważane za wzorce i są rozwijane do listy plików pasujących do tego wzorca.
W związku z for i in $(xrandr)tym $(xrandr), ponieważ nie ma go w cudzysłowie, jest podzielony na ciągi znaków spacji, tabulacji i nowego wiersza. Każde słowo powstałe w wyniku tego podziału jest sprawdzane pod kątem pasujących nazw plików (lub pozostawione tak, jakby nie pasowały do żadnego pliku) i forzapętla je wszystkie.
W for i in "$(xrandr)"nie używamy operatora split + glob, ponieważ cytowane jest podstawienie polecenia , więc w pętli jest jedno przejście na jedną wartość: wynik xrandr(bez końcowych znaków nowego wiersza, które pasują do zastępowania poleceń ).
Jednak w echo $i, $inie jest ponownie cytowany, więc ponownie treść $ijest podzielona i podlega generowaniu nazw plików, a te są przekazywane jako osobne argumenty do echopolecenia (i echowyprowadzają jego argumenty oddzielone spacjami).
Lekcja nauczyła się:
- jeśli nie chcesz dzielenia słów ani generowania nazw plików , zawsze podawaj rozszerzenia zmiennych i podstawienia poleceń
- jeśli chcesz podzielić słowa lub generować nazwy plików , pozostaw je bez cudzysłowu, ale
$IFSodpowiednio je ustaw i / lub włącz lub wyłącz generowanie nazw plików w razie potrzeby ( set -f, set +f).
Zazwyczaj w powyższym przykładzie, jeśli chcesz zapętlić pustą, oddzieloną listę słów na wyjściu xrandr, musisz:
- pozostaw
$IFSwartość domyślną (lub usuń ją), aby podzielić na puste
- Zastosowanie
set -fdo wyłączenia generowania nazw plików, chyba że jesteś pewien, że xrandrnigdy nie wyprowadza dowolny *lub ?lub [znaków (które są symbole wieloznaczne stosowane we wzorcach generacji filename)
A następnie używaj tylko operatora split + glob (pozostaw tylko zastępowanie poleceń lub rozwijanie zmiennych bez cudzysłowu) w inczęści forpętli:
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
Jeśli chcesz zapętlić (niepuste) linie danych xrandrwyjściowych, musisz ustawić $IFSznak nowej linii:
IFS='
'