Що таке "IFS"?


Відповіді:


17

IFSрозшифровується - це символ, який розділяє поля. У наведеному вами прикладі встановлено новий символ рядка ( ); тому після його встановлення оброблятиме текст за рядком. У цьому прикладі ви можете змінити значенняInput Internal Field Separator\nforIFS (на якусь букву, що є у вашому вхідному файлі) і перевірити, як текст буде розділений.

До речі, з відповіді, яку ви опублікували, друге рішення, що рекомендується ...

Як зауважив @jasonwryan , це не Inputтак Internal. Назва Inputпоходить від того, awkв якому також є OFS- Output Field Separator.


1
Зауважте, що IFS також використовується для комбінування параметрів для виведення. З сторінки bash man: "Коли розширення відбувається в межах подвійних лапок, воно розширюється на одне слово зі значенням кожного параметра, розділеним першим символом спеціальної змінної IFS."
Ерік

Слід також зазначити, що в той час Sбув для сепаратора в оболонці Борна, звідки він походить. У оболонці Корна та більшості інших оболонок, подібних до Борна, як це було визначено зараз POSIX, Sце для Делімітера (просто розтягніть свою фантазію), як, A::B:наприклад, розділено на "А", "" і "В" (без зайвих ""). Це відрізняється від awk's FSабо sпрапора розширення параметра zsh.
Стефан Шазелас

27

IFSне має безпосереднього відношення до циклу, це пов'язано з розділенням слів. IFSопосередковано визначає, як вихід з команди розбивається на частини, які цикл повторює.

Якщо у вас є незахищена підміна змінної $fooабо підміна команд $(foo), є два випадки:

  • Якщо контекст очікує одного слова, наприклад, коли підміна знаходиться між подвійними лапками "$foo"або в призначенні змінної x=$foo, то рядок, що виникає в результаті заміни, використовується як є.
  • Якщо контекст очікує на кілька слів, що трапляється в більшості випадків, то в отриманій рядку виконуються два наступні розширення:
    • Рядок розділений на слова . Будь-який символ, який з’являється у $IFS, вважається роздільником слів. Наприклад, IFS=":"; foo="12:34::78"; echo $fooвідбитки 12 34 ​ 78(з двома пробілами між 34та78 , оскільки там порожнє слово).
    • Кожне слово трактується як глобальний зразок і розгортається до списку імен файлів . Наприклад, foo="*"; echo $fooдрукує список файлів у поточному каталозі.

Для циклів, як і багатьох інших контекстів, очікуйте список слів. Так

for x in $(foo); do 

розбивається $(foo)на слова і розглядає кожне слово як глобальний зразок. Значенням за замовчуванням IFSє пробіл, вкладка та новий рядок , тому, якщо fooвиводиться два рядки, hello worldа howdyпотім виконується тіло циклу x=hello, тоді x=worldі x=howdy. Якщо IFSявно змінено, щоб містити тільки новий рядок, тоді цикл виконується для hello worldі howdy. Якщо IFSзмінюється , щоб бути o, то цикл виконується для hell, ​ w, rld​␤h(де ​␤це символ нового рядка) і wdy.


Чому ви згадували "Побічно" у "IFS indirectly determines how ..."?
αғsnιη

1
@ αғsnιη IFS(безпосередньо) визначає, як розбивається вихід підстановки команд, яка потім (опосередковано) визначає, над чим цикл перетворюється.
Жил "ТАК - перестань бути злим"

5

З man bash

IFS Внутрішній розділювач поля, який використовується для розбиття слів після розширення та для розділення рядків на слова за допомогою прочитаної команди вбудованої команди. Значенням за замовчуванням є "<pace> <tab> <newline>".

Це одна із внутрішніх змінних Баша. Він визначає, як Bash розпізнає поля чи межі слів при інтерпретації рядків символів.

Незважаючи на те, що це пробіл у пробілі (пробіл, вкладка та новий рядок), він може бути змінений, наприклад, для розбору файлів даних, розділених комами.

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


0

На додаток до попередніх чудових відповідей, дозвольте лише додати, що IFS дуже корисний для ефективного та портативного розбору в простих випадках у поєднанні з набором . Ефективна, тому що уникає використання допоміжних оболонок та нерестових інструментів, таких як grep або 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

Просто зауважте, що нам потрібно зберігати та відновити попереднє значення IFS, щоб уникнути небажаних поломок в інших частинах скрипту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.