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ą $IFS
zmiennej 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 for
zapę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
, $i
nie jest ponownie cytowany, więc ponownie treść $i
jest podzielona i podlega generowaniu nazw plików, a te są przekazywane jako osobne argumenty do echo
polecenia (i echo
wyprowadzają 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
$IFS
odpowiednio 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
$IFS
wartość domyślną (lub usuń ją), aby podzielić na puste
- Zastosowanie
set -f
do wyłączenia generowania nazw plików, chyba że jesteś pewien, że xrandr
nigdy 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 in
części for
pętli:
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
Jeśli chcesz zapętlić (niepuste) linie danych xrandr
wyjściowych, musisz ustawić $IFS
znak nowej linii:
IFS='
'