zrozumienie domyślnej wartości IFS

10

W mojej wersji GNU bash 4.2.8 IFS domyślnie ma domyślną wartość spacji, tabulacji i przesunięcia wiersza:

usr@T42 ~ $ echo -n "$IFS" | hexdump -C
00000000  20 09 0a                                          | ..|
00000003
usr@T42 ~ $ 

Czy istnieje powód takiego domyślnego IFS? Ponadto, które narzędzia używają IFS oprócz wbudowanego bash read?

Jaskółka oknówka
źródło

Odpowiedzi:

13

Zmienna IFS jest używana za każdym razem, gdy powłoka wykonuje zadanie zwane dzieleniem słów . Najczęstsze przypadki, w których jest to używane, to po rozwinięciu parametru (np. $var) Lub zastąpieniu polecenia (np. $(some-command)Lub przestarzałe znaki wstecz) w poleceniu. Tutaj, jeśli rozwinięcie zawiera jakieś IFSznaki, to przed przetworzeniem polecenia dzieli się na różne „słowa”. W efekcie oznacza to, że znaki te dzielą podstawiony tekst na różne argumenty (w tym nazwę polecenia, jeśli zmienna jest określona jako pierwsza).

Dlatego przyczyną domyślnej wartości IFSspacji, tabulacji i nowej linii jest to, że są to białe znaki, które normalnie powinny podzielić słowo.

Jednym ze sposobów zapobiegania dzieleniu się słów jest stosowanie podwójnych cudzysłowów wokół interpretacji ( "$var") - w rzeczywistości zrobiłeś to w swoim pytaniu. Gdybyś tego nie zrobił, nie byłoby danych wyjściowych, echoponieważ nie miałby żadnych argumentów, tylko znaki dzielące argumenty.

Zauważ też, że dwa miejsca, w których dzielenie słów nie następuje po rozwinięciu parametru, mają przypisanie zmiennych (np. var=$othervarI var=$(somecommand)jest w porządku) oraz w obrębie [[ ]]konstrukcji ( [[ $var = $othervar ]]jest w porządku, ale [ $var = $othervar ]należy je zacytować).

Wreszcie, jak kiedyś wskazał mi mądry człowiek, powszechnym nieporozumieniem jest to, że zapobieganie podziałowi słów jest jedynym powodem cytowania zmiennej. Nie jest tak, ponieważ cytowanie zapobiega również rozwijaniu nazw ścieżek lub rozwijaniu globów, ponieważ jest to bardziej znane. Jeśli zmienna zawiera takie znaki globalne, *to można je rozwinąć do nazw plików, gdy zmienna jest używana w cudzysłowie. Np. Rozważ:

var=*
echo $var

Spowoduje to wyświetlenie nazw plików w bieżącym katalogu.

Jak wskazuje Stephane poniżej , kolejność znaków IFSjest znacząca podczas rozwijania "$*". Ze strony podręcznika bash:

"$*" is equivalent to "$1c$2c...", where c is the first character of the value of
the IFS variable.  If IFS is unset, the parameters are separated by spaces.  If
IFS is null, the parameters are joined without intervening separators.

Więcej przykładów podziału słów można znaleźć w tej odpowiedzi - https://unix.stackexchange.com/a/118444/48083

Graeme
źródło
1
$IFSUżywa się również pierwszego znaku, w "$*"którym kolejność ma znaczenie.
Stéphane Chazelas
2
Zauważ też, że zshdomyślnie zawiera znak NUL $IFS(inne powłoki nie obsługują przechowywania znaku NUL w swoich zmiennych).
Stéphane Chazelas