Czytałem ten wątek: Jak zapętlić linie wiersza pliku?
Co to jest IFS? A jakie jest jego użycie w kontekście forpę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 forpętli?
Odpowiedzi:
IFSoznacza - 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.InputInternal Field Separator\nforIFS
BTW, z opublikowanej odpowiedzi drugie rozwiązanie jest takie, które zaleca ...
Jak zauważył @jasonwryan , nie jest to Inputale Internal. Nazwa Inputpochodzi od tego, awkw którym jest również OFS- Output Field Separator.
Sbył 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, Sdotyczy 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 FSlub z sflagą ekspansji parametr zsh.
IFSnie jest bezpośrednio związany z zapętlaniem, jest związany z dzieleniem słów. IFSpoś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 $foolub 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.$IFSjest traktowany jako separator słów. Na przykład IFS=":"; foo="12:34::78"; echo $foodrukuje 12 34 78(z dwiema spacjami między 34i 78, ponieważ jest puste słowo).foo="*"; echo $foodrukuje 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ą IFSjest spacja, tabulator i nowa linia , więc jeśli foodrukuje dwie linie, hello worlda howdynastępnie wykonuje się treść pętli x=hello, to x=worldi x=howdy. Jeśli IFSzostanie wyraźnie zmieniony, aby zawierał tylko nowy wiersz, wówczas pętla jest wykonywana dla hello worldi howdy. Jeśli IFSzmienia 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.