Основна ідея полягає в тому, що VAR=VALUE some-commandнабори VARдля VALUEдля виконання , some-commandколи some-commandє зовнішня команда, і вона не отримує більше фантазії , ніж це. Якщо ви поєднуєте цю інтуїцію з деякими знаннями про те, як працює оболонка, у більшості випадків вам слід підійти з правильною відповіддю. Посилання POSIX - "Прості команди" у розділі "Мова командної оболонки" .
Якщо some-commandце зовнішня команда , VAR=VALUE some-commandеквівалентна env VAR=VALUE some-command. VARекспортується в середовище some-command, і його значення (або відсутність значення) в оболонці не змінюється.
Якщо some-commandце функція , то VAR=VALUE some-commandвона еквівалентна VAR=VALUE; some-command, тобто присвоєння залишається на місці після повернення функції, а змінна не експортується в середовище. Причина цього пов'язана з дизайном оболонки Борна (а згодом і з зворотною сумісністю): він не мав можливості зберігати та відновлювати змінні значення навколо виконання функції. Не експортувати змінну має сенс, оскільки функція виконується в самій оболонці. Однак, ksh (включаючи ATT ksh93 та pdksh / mksh), bash та zsh реалізують більш корисну поведінку, де VARвстановлено лише під час виконання функції (вона також експортується). У ksh це робиться, якщо функція визначена синтаксисом kshfunction NAME …, не якщо це визначено зі стандартним синтаксисом NAME (). У bash це робиться тільки в режимі bash, а не в режимі POSIX (при запуску з POSIXLY_CORRECT=1). У zsh це робиться, якщо posix_builtinsпараметр не встановлений; ця опція не встановлена за замовчуванням, але увімкнена emulate shабо emulate ksh.
Якщо some-commandвбудований, поведінка залежить від типу вбудованого. Спеціальні вбудовані поводяться як функції. Спеціальні вбудовані модулі - це ті, які потрібно реалізувати всередині оболонки, оскільки вони впливають на стан оболонки (наприклад, breakвпливають на керуючий потік, cdвпливають на поточний каталог, setвпливають на позиційні параметри та параметри ...). Інші вбудовані вбудовані лише для продуктивності та зручності (в основному - наприклад, функцію bash printf -vможе реалізовувати лише вбудований), і вони поводяться як зовнішня команда.
Присвоєння відбувається після розширення псевдоніма, тому, якщо some-commandце псевдонім , спершу розгорніть його, щоб знайти те, що відбувається.
Зауважте, що у всіх випадках призначення виконується після розбору командного рядка, включаючи будь-яку заміну змінної в самому командному рядку. Отже, var=a; var=b echo $varдрукується a, тому що $varоцінюється до того, як відбудеться завдання. І таким чином IFS=. printf "%s\n" $varвикористовує старе IFSзначення для розділення $var.
Я охоплював усі типи команд, але є ще один випадок: коли немає команди для виконання , тобто якщо команда складається лише з призначень (і, можливо, перенаправлень). У цьому випадку завдання залишається на місці . VAR=VALUE OTHERVAR=OTHERVALUEеквівалентно VAR=VALUE; OTHERVAR=OTHERVALUE. Отже після IFS=. arr=($var), IFSзалишається налаштованим .. Оскільки ви можете використовувати $IFSв призначенні до arrтого, що він вже має нове значення, має сенс, що нове значення IFSвикористовується для розширення $var.
Підсумовуючи, ви можете використовувати лише IFSдля тимчасового поділу поля:
- запустивши нову оболонку або підшару (наприклад
third=$(IFS=.; set -f; set -- $var; echo "$3"), це складний спосіб виконання, third=${var#*.*.}за винятком того, що вони ведуть себе по-різному, коли значення varмістить менше двох .символів);
- в ksh,
IFS=. some-functionде some-functionвизначено синтаксисом ksh function some-function …;
- в bash і zsh,
IFS=. some-functionякщо вони працюють в рідному режимі на відміну від режиму сумісності.
IFSзалишається встановленим." Eek. Прочитавши першу частину, це має сенс, але перед тим, як я опублікував цю Q, я б цього не очікував.