Czytałem ten wątek: Jak zapętlić linie wiersza pliku?
Co to jest IFS
? A jakie jest jego użycie w kontekście for
pętli?
Czytałem ten wątek: Jak zapętlić linie wiersza pliku?
Co to jest IFS
? A jakie jest jego użycie w kontekście for
pętli?
Odpowiedzi:
IFS
oznacza - to znak, który oddziela pola. W opublikowanym przykładzie jest on ustawiony na znak nowej linii ( ); więc po ustawieniu przetworzy tekst wiersz po wierszu. W tym przykładzie możesz zmienić wartość (na jakąś literę, którą masz w pliku wejściowym) i sprawdzić, w jaki sposób tekst zostanie podzielony.Input
Internal Field Separator
\n
for
IFS
BTW, z opublikowanej odpowiedzi drugie rozwiązanie jest takie, które zaleca ...
Jak zauważył @jasonwryan , nie jest to Input
ale Internal
. Nazwa Input
pochodzi od tego, awk
w którym jest również OFS
- Output Field Separator
.
S
był dla separatora w powłoce Bourne'a, skąd pochodzi. W skorupie Korna i większości innych powłok podobnych do Bourne'a, jak to teraz określono POSIX
, S
dotyczy Delimitera (po prostu trochę rozciągnij swoją wyobraźnię), ponieważ A::B:
na przykład jest podzielony na „A”, „” i „B” (bez dodatkowych „”). To różni się od awk
„s FS
lub z s
flagą ekspansji parametr zsh
.
IFS
nie jest bezpośrednio związany z zapętlaniem, jest związany z dzieleniem słów. IFS
pośrednio określa, w jaki sposób dane wyjściowe polecenia są dzielone na części, nad którymi iteruje się pętla.
W przypadku niezabezpieczonego podstawienia zmiennej $foo
lub podstawienia polecenia $(foo)
występują dwa przypadki:
"$foo"
lub w przypisaniu zmiennym x=$foo
, wówczas łańcuch wynikający z podstawienia jest używany jak jest.$IFS
jest traktowany jako separator słów. Na przykład IFS=":"; foo="12:34::78"; echo $foo
drukuje 12 34 78
(z dwiema spacjami między 34
i 78
, ponieważ jest puste słowo).foo="*"; echo $foo
drukuje listę plików w bieżącym katalogu.Pętle, podobnie jak wiele innych kontekstów, oczekują listy słów. Więc
for x in $(foo); do …
rozkłada się $(foo)
na słowa i traktuje każde słowo jako wzór globalny. Domyślną wartością IFS
jest spacja, tabulator i nowa linia , więc jeśli foo
drukuje dwie linie, hello world
a howdy
następnie wykonuje się treść pętli x=hello
, to x=world
i x=howdy
. Jeśli IFS
zostanie wyraźnie zmieniony, aby zawierał tylko nowy wiersz, wówczas pętla jest wykonywana dla hello world
i howdy
. Jeśli IFS
zmienia się być o
, to pętla jest wykonywana na hell
, w
, rldh
(gdzie 
jest znak nowej linii) i wdy
.
"IFS indirectly determines how ..."
?
IFS
(bezpośrednio) określa, w jaki sposób rozkłada się wynik podstawienia polecenia, co następnie (pośrednio) określa, przez co pętla przechodzi.
Od man bash
IFS Wewnętrzny separator pól używany do dzielenia słów po rozwinięciu i dzielenia linii na słowa za pomocą wbudowanego polecenia odczytu. Wartość domyślna to „<space> <tab> <newline>”.
Jest to jedna ze zmiennych wewnętrznych Basha. Określa, w jaki sposób Bash rozpoznaje pola lub granice słów, gdy interpretuje ciągi znaków.
Domyślnie jest to spacja (spacja, tabulator i znak nowej linii), ale można go zmienić, na przykład, aby przeanalizować plik danych oddzielony przecinkami.
Oprócz poprzednich świetnych odpowiedzi, dodam tylko, że IFS jest bardzo przydatny do wydajnego i przenośnego parsowania w prostych przypadkach w połączeniu z zestawem . Wydajny, ponieważ pozwala uniknąć używania podpowłok i narzędzi spawnujących, takich jak grep lub sed:
resolutions="640x480,320x240"
xIFS=$IFS
IFS=','
for res in $resolutions; do
xxIFS=$IFS
IFS='x'
set -- $res
width=$1
height=$2
# handle width and height
IFS=$xxIFS
done;
IFS=$xIFS
Pamiętaj tylko, że musimy przechowywać i odzyskiwać poprzednią wartość IFS, aby uniknąć niepożądanych awarii w innych częściach skryptu.