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

13

В dash функции и переменные, кажется, живут в отдельных пространствах имен:

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?

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

Ответы:

13

Гарантия :

2.9.5 Команда определения функции

Функция - это пользовательское имя, которое используется как простая команда для вызова составной команды с новыми позиционными параметрами. Функция определяется с помощью «команды определения функции». [...]

Функция называется fname; приложение должно убедиться, что это имя (см. Имя XBD) и что это не имя специальной встроенной утилиты. Реализация может разрешить другие символы в имени функции в качестве расширения. Реализация должна поддерживать отдельные пространства имен для функций и переменных.

ilkkachu
источник
Также обратите внимание, что unsetесть -vи -fвыбирать между отменой установки переменной или функции по заданному имени. bash(в отличие от большинства других оболочек) будет сбросить на foo функцию с , unset fooесли нет fooпеременной (!), поведение , допускаемое POSIX. Вот почему в сценариях POSIX это хорошая практика , чтобы всегда использовать либо -vили -f(и, конечно , в bashсценариях , а также, но учтите , что unsetне всегда может UNSET переменной в bash, bashпеременная обзорное имеет довольно много проблем).
Стефан Шазелас
Обратите внимание, что в bash перед загрузкой оболочки вы можете столкнуться с проблемами при экспорте как переменной, так и функции по заданному имени, так как bash будет использовать одно и то же имя переменной среды (если дважды ввести его в среду, некоторые команды могут удалить один из них)
Стефан Шазелас
8

Переменные и функции находятся в разных пространствах имен в тире, и это также указывается в POSIX :

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

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

Итак, да, поведение, которое вы видите, гарантируется POSIX.

POSIX не стандартизированы local , пока :

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

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

(акцент мой)

maxschlepzig
источник
ash (с конца 80-х), на которой базируется dash, также имеет localодин из наиболее стабильных интерфейсов (по сравнению с сильно сломанным в bash, например), bash только недавно (4.4) заимствовал local -(для локальной области видимости для варианты) из золы (реализация масштабирования в стиле пепла только для этой одной $-переменной). ksh и yash не имеют local( есть только варианты pdksh local), но имеют typesetвместо этого (в ksh93 typesetобеспечивает локальную (статическую) область видимости только в функциях, объявленных с использованием синтаксиса ksh).
Стефан Шазелас