функции оболочки и переменные с одинаковыми именами

Вы можете выполнять их параллельно с помощью ... gnu parallel:

parallel "sh script.sh {} > {}.out" ::: *
4
06.03.2019, 00:28
2 ответа

То же самое происходит и в Emacs Lisp. Он имеет два пространства имен, одно для функций и одно для переменных. Если вы разыменовываете символ в контексте функции ((var)), он вызовет функцию, если вы разыменовываете его в контексте переменной (var, то есть без скобок ), он даст вам переменную. Например:

(defun myvar (myvar)
  "adds 3 to MYVAR"
  (+ 3 myvar))
(setq myvar 7)
(message (myvar myvar))

Выполнит функцию myvarс аргументом 7, который является разыменованием переменной myvar.

Это может стать очень запутанным, если вы к этому не привыкли.

Посмотрев на ваш вопрос и проведя тесты для bash , я удивлен, что он демонстрирует такое же поведение. Перевод ELisp сверху на bash:

[grochmal@phoenix ~]$ myvar () { echo $(($1+3)); }
[grochmal@phoenix ~]$ myvar=7
[grochmal@phoenix ~]$ myvar $myvar
10

Bash немного менее запутан в этом, чем ELisp, потому что вам нужен $, чтобы пометить переменную. Тем не менее, это может выглядеть как declareодного имени, состоящего из двух вещей. См.:

[grochmal@phoenix ~]$ declare -p myvar
declare -x myvar="7"
[grochmal@phoenix ~]$ declare -f myvar
myvar () 
{ 
    echo $(($1+3))
}

(П.С. Как только вы привыкнете к существованию двух пространств имен, например. вы программируете на ELisp какое-то время, это перестает сбивать с толку)

2
27.01.2020, 20:52

Общая история :отдельные пространства имен

Обычно оболочки различают переменные и функции, потому что они используются в разных контекстах. В двух словах, имя является именем переменной, если оно появляется после $или в качестве аргумента встроенных функций, таких какexport(без-funset(без-f). Имя является именем функции, если оно появляется как команда (после раскрытия псевдонима )или как аргумент для export -f, unset -fи т. д.

Переменные можно экспортировать в среду. Имя переменной среды такое же, как и у переменной оболочки (, и значения такие же ).

Со старым bash :путаница из-за экспорта функции

Bash, в отличие от большинства других оболочек, также может экспортировать функции в среду. Поскольку в среде нет индикации типа, нет никакого способа узнать, является ли запись в среде функцией или нет, кроме как путем анализа имени или значения переменной среды.

Старые версии bash хранили функцию в среде, используя имя функции в качестве имени и что-то похожее на определение функции в качестве значения функции. Например:

bash-4.1$ foobar () { echo foobar; }
bash-4.1$ export -f foobar
bash-4.1$ env |grep -A1 foobar
foobar=() {  echo foobar
}
bash-4.1$ 

Обратите внимание, что невозможно отличить функцию с кодом { echo foobar; }от переменной со значением () { echo foobar␤}(, где — символ новой строки ). Это оказалось неудачным дизайнерским решением.

Иногда сценарии оболочки вызываются с переменными среды, значение которых находится под контролем потенциально враждебной сущности. Например, CGI-скрипты. Функция экспорта/импорта функций Bash позволяла вводить функции таким образом. Например, выполнение скрипта

#!/bin/bash
ls

из удаленного запроса безопасен, если среда не содержит переменных с определенным именем (, напримерPATH). Но если запрос может установить переменную среды lsв () { cat /etc/passwd; }, тогда bash с радостью выполнит cat /etc/passwd, поскольку это тело функции ls.

С новым bash :путаница в основном устранена

Эта уязвимость системы безопасности была обнаружена Стефаном Шазела как один из аспектов ошибки Shellshock . В версиях bash после -Shellshock экспортированные функции идентифицируются по имени , а не по содержимому.

bash-4.3$ foobar () { echo foobar; }
bash-4.3$ export -f foobar
bash-4.3$ env |grep -A1 foobar
BASH_FUNC_foobar%%=() {  echo foobar
}

Теперь нет проблем с безопасностью, потому что такие имена, как BASH_FUNC_foobar%%, обычно не используются в качестве имен команд и могут быть отфильтрованы интерфейсами, которые позволяют передавать переменные среды.Технически возможно иметь символ %в имени переменной окружения (, это то, что заставляет работать экспортируемые функции современного bash ), но обычно люди этого не делают, потому что оболочки не принимают %в имя переменной.

Предложение в руководстве bash относится к старому поведению (до -Shellshock ). Его следует обновить или удалить. В современных версиях bash в среде нет двусмысленности, если вы предполагаете, что переменные среды не будут иметь имя, оканчивающееся на %%.

5
27.01.2020, 20:52

Теги

Похожие вопросы