Окремі простори імен для функцій та змінних в оболонках POSIX


13

У тирі функції та змінні, схоже, живуть в окремих просторах імен:

fn(){
    fn="hello world"
}
fn; echo "The value is $fn!" #prints: The value is hello world!
fn; echo "The value is $fn!" #prints: The value is hello world!
#the fn variable doesn't conflict with the fn function

Це особливість тире чи гарантія POSIX?


2
Ваш код насправді не підтверджує, що fnфункція знаходиться в окремому просторі імен; якби його виконання колись викреслило його визначення, ми побачили б точно таку ж поведінку. Ви повинні показати, що функція все-таки визначена, наприклад, type fnпісля цього.
alexis

Відповіді:


13

Гарантія :

2.9.5 Команда визначення функції

Функція - визначене користувачем ім'я, яке використовується як проста команда для виклику складеної команди з новими позиційними параметрами. Функція визначається за допомогою "команди визначення функції". [...]

Функція названа fname; додаток повинен переконатися, що це ім’я (див. Ім'я XBD) і що це не ім’я спеціальної вбудованої утиліти. Реалізація може дозволити іншим символам у назві функції як розширення. Реалізація повинна підтримувати окремі простори імен для функцій та змінних.


Також зауважте, що unsetє -vі -fвибирати між неставленням змінної чи функції вказаним іменем. bash(На відміну від більшості інших оболонок) буде скинути на foo функцію з , unset fooякщо немає fooзмінної (!), Поведінка , допустиме POSIX. Ось чому в сценаріях POSIX є гарною практикою завжди використовувати або -vабо -f(і, звичайно, також у bashскриптах, але зауважте, що unsetне завжди може бути скинуто змінну в bash, bashзмінне масштабування має досить багато питань).
Стефан Шазелас

Зауважте, що у програмі bas-shell bash у вас виникнуть проблеми при експорті змінної та функції за вказаним іменем, оскільки bash в кінцевому підсумку використовує однакове ім’я змінної середовища для обох (помістивши його двічі в оточення, деякі команди можуть видалити один з них)
Стефан Шазелас

8

Змінні та функції знаходяться в різних просторах імен на тире, і це також визначено POSIX :

Реалізація повинна підтримувати окремі простори імен для функцій та змінних.

Крім цього, змінні мають за замовчуванням глобальний обсяг. Деякі оболонки (наприклад, bash, ksh та zsh) надають localключовому слову для оголошення змінних у функції лише з локальним діапазоном.

Отже, так, поведінка, яку ви бачите, гарантується POSIX.

POSIX НЕ стандартизовані local , поки :

Опис функцій у першій пропозиції базувався на уявленні, що функції повинні вести себе як мініатюрні сценарії оболонки; тобто, крім спільного використання змінних , більшість елементів середовища виконання повинні поводитись так, ніби вони є новим середовищем виконання, [..]

[..] Локальні змінні в межах функції були розглянуті та включені в іншу ранню пропозицію (керовану спеціальним вбудованим local), але їх видалили, оскільки вони не відповідають простої моделі, розробленої для функцій, і тому, що існує певна опозиція до додавання ще один новий спеціальний вбудований, який не входив до історичної практики. Реалізація повинна резервувати ідентифікатор local(а також typeset, як використовується у KornShell) у випадку, якщо цей локальний змінний механізм буде прийнятий у майбутній версії цього стандарту.

(наголос мій)


зола (з кінця 80-х років), на якій ґрунтується тире, також має localодин з найбільш послідовних інтерфейсів (порівняно з сильно розбитим у баші, наприклад), bash лише нещодавно (4.4) запозичив local -(для локальної сфери для параметри) з золи (реалізуючи масштабування стилю золи $-лише для цієї змінної). ksh та yash не мають local(лише у варіантах pdksh local), але мають typesetнатомість (у ksh93 typesetнадає локальну (статичну) область застосування лише у функціях, оголошених за допомогою синтаксису ksh).
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.