После прочтения 24.2. Локальные переменные , я думал, что объявление переменной var
с ключевым словом local
означало, что var
значение было доступно только внутри блока кода, ограниченного фигурными скобками функции.
Однако после запуска следующего примера, я обнаружил, что var
также может быть доступна, и считываться из функций , вызываемых этого блоком кода - то есть , даже если var
декларируются local
к outerFunc
, innerFunc
все еще в состоянии прочитать и изменить его значение.
#!/usr/bin/env bash
function innerFunc() {
var='new value'
echo "innerFunc: [var:${var}]"
}
function outerFunc() {
local var='initial value'
echo "outerFunc: before innerFunc: [var:${var}]"
innerFunc
echo "outerFunc: after innerFunc: [var:${var}]"
}
echo "global: before outerFunc: [var:${var}]"
outerFunc
echo "global: after outerFunc: [var:${var}]"
Выход:
global: before outerFunc: [var:] # as expected, `var` is not accessible outside of `outerFunc`
outerFunc: before innerFunc: [var:initial value]
innerFunc: [var:new value] # `innerFunc` has access to `var` ??
outerFunc: after innerFunc: [var:new value] # the modification of `var` by `innerFunc` is visible to `outerFunc` ??
global: after outerFunc: [var:]
Q: Это ошибка в моей оболочке (bash 4.3.42, Ubuntu 16.04, 64bit) или это ожидаемое поведение?
РЕДАКТИРОВАТЬ: Решено. Как отмечает @MarkPlotnick, это действительно ожидаемое поведение.
var
пусто?var
установлен глобальноinnerFunc
, так почему же он не придерживается до конца скрипта?Ответы:
Переменные оболочки имеют динамическую область видимости . Если переменная объявлена как локальная для функции, эта область остается до тех пор, пока функция не вернется.
Есть два исключения:
в ksh93, если функция определена со стандартным
function_name () { … }
синтаксисом, то ее локальные переменные подчиняются динамической области видимости. Но если функция определена с синтаксисом ksh,function function_name { … }
то ее локальная переменная подчиняется лексической / статической области видимости, поэтому они не видны в других функциях, вызываемых этим.zsh/private
autoloadable плагин вzsh
позволяет сprivate
ключевым словом / встроенным который может быть использовано , чтобы объявить переменный со статической сферой.ash, bash, pdksh и производные, bosh имеют только динамическую область видимости.
источник
local
?typeset
илиdeclare
илиlocal
, область действия пока функция не вернется. Без такой декларации область действия является глобальной.Это не ошибка, вызов в контексте externalFunc использует эту локальную копию $ var. «Local» в externalFunc означает, что глобальное не изменилось. Если вы вызываете innerFunc вне externalFunc, то произойдет изменение в глобальном $ var, но не в локальный $ var externalFunc. Если бы вы добавили «local» к innerFunc, то $ var externalFunc не изменился бы - по сути, их было бы 3:
использовать формат пространства имен Perl, вроде.
источник
Вы можете использовать функцию для форсирования локальной области видимости:
Пример:
Результат:
Источник
источник
В не был объявлен как местный , поэтому он доступен в видимом объеме (после того , как функция была вызвана).
function innerFunc()
var='new value'
И наоборот, в был объявлен как местный , поэтому он не доступен в глобальной области (даже если функция была вызвана).
function outerFunc()
local var='initial value'
Поскольку он
innerFunc()
был вызван как потомокouterFunc()
, var находится в локальной области видимостиouterFunc()
.man 1 bash
может помочь уточнитьПодразумеваемое поведение, которое ожидается в описании, может быть достигнуто путем объявления
local var='new value
вfunction innerFunc()
.Как уже говорили другие, это не ошибка в оболочке bash. Все работает как надо.
источник
var
в глобальном масштабе, после вызоваinnerFunc
черезoutFunc
, не печатаетnew value
.