Основна ідея полягає в тому, що 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, я б цього не очікував.