Co to jest „IFS”?


Odpowiedzi:


17

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.Input Internal 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.


1
Zauważ, że IFS służy również do łączenia parametrów wyjściowych. Ze strony podręcznika użytkownika bash: „Gdy rozwinięcie występuje w obrębie podwójnych cudzysłowów, rozwija się do pojedynczego słowa z wartością każdego parametru oddzieloną pierwszym znakiem zmiennej specjalnej IFS.”
Eric

Należy również zauważyć, że podczas gdy 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.
Stéphane Chazelas,

27

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:

  • Jeśli w kontekście oczekuje się pojedynczego słowa, np. Gdy podstawienie występuje między podwójnymi cudzysłowami "$foo"lub w przypisaniu zmiennym x=$foo, wówczas łańcuch wynikający z podstawienia jest używany jak jest.
  • Jeśli kontekst oczekuje wielu słów, co ma miejsce najczęściej, wówczas w wynikowym ciągu wykonywane są dwa kolejne rozwinięcia:
    • Ciąg jest podzielony na słowa . Każdy pojawiający się znak $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).
    • Każde słowo jest traktowane jako wzorzec globalny i jest rozwijane do listy nazw plików . Na przykład 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, rld​␤h(gdzie ​␤jest znak nowej linii) i wdy.


Dlaczego wspominałeś „Pośrednio” w "IFS indirectly determines how ..."?
αғsнιη

1
@ αғsнιη 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.
Gilles „SO- przestań być zły”

5

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.

http://tldp.org/LDP/abs/html/internalvariables.html


0

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.