Я читав цю тему: Як перевести цикл на рядки файлу?
Що таке IFS
? І яке його використання в контексті for
-loops?
Я читав цю тему: Як перевести цикл на рядки файлу?
Що таке IFS
? І яке його використання в контексті for
-loops?
Відповіді:
IFS
розшифровується - це символ, який розділяє поля. У наведеному вами прикладі встановлено новий символ рядка ( ); тому після його встановлення оброблятиме текст за рядком. У цьому прикладі ви можете змінити значенняInput
Internal Field Separator
\n
for
IFS
(на якусь букву, що є у вашому вхідному файлі) і перевірити, як текст буде розділений.
До речі, з відповіді, яку ви опублікували, друге рішення, що рекомендується ...
Як зауважив @jasonwryan , це не Input
так Internal
. Назва Input
походить від того, awk
в якому також є OFS
- Output Field Separator
.
S
був для сепаратора в оболонці Борна, звідки він походить. У оболонці Корна та більшості інших оболонок, подібних до Борна, як це було визначено зараз POSIX
, S
це для Делімітера (просто розтягніть свою фантазію), як, A::B:
наприклад, розділено на "А", "" і "В" (без зайвих ""). Це відрізняється від awk
's FS
або s
прапора розширення параметра zsh
.
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
, rldh
(де 
це символ нового рядка) і wdy
.
"IFS indirectly determines how ..."
?
IFS
(безпосередньо) визначає, як розбивається вихід підстановки команд, яка потім (опосередковано) визначає, над чим цикл перетворюється.
З man bash
IFS Внутрішній розділювач поля, який використовується для розбиття слів після розширення та для розділення рядків на слова за допомогою прочитаної команди вбудованої команди. Значенням за замовчуванням є "<pace> <tab> <newline>".
Це одна із внутрішніх змінних Баша. Він визначає, як Bash розпізнає поля чи межі слів при інтерпретації рядків символів.
Незважаючи на те, що це пробіл у пробілі (пробіл, вкладка та новий рядок), він може бути змінений, наприклад, для розбору файлів даних, розділених комами.
На додаток до попередніх чудових відповідей, дозвольте лише додати, що 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, щоб уникнути небажаних поломок в інших частинах скрипту.