Невозможно иметь локальную переменную с тем же именем, что и глобальная переменная только для чтения

Используя bash, вы можете использовать GLOBIGNORE :

$ ls -d1 *
excludeme(2015)
excludmetoo(2016)
somedir

$ GLOBIGNORE='*)'
$ ls -d1 *
somedir

GLOBIGNORE:

Список шаблонов, разделенных двоеточиями, определяющих набор имен файлов, которые будут игнорироваться расширением имени файла. Если имя файла, совпадающее с шаблоном раскрытия имени файла , также соответствует одному из шаблонов в GLOBIGNORE, оно удаляется из списка совпадений.

2
13.03.2019, 06:09
2 ответа

Насколько мне известно, такое поведение можно назвать «Работа как дизайн». У вас есть переменная только для чтения, и идея в том, что вы не можете изменить значение этой переменной. В bash у вас нет возможности определить переменную, которая перезаписывает набор таких глобальных переменных.

0
27.01.2020, 22:27

Похоже, что Bash не может скрывать глобальные переменные только для чтения. Я подозреваю, что это следствие того, что Posix не имеет областей видимости для переменных, кроме $@. Однако локальные переменные только для чтения могут быть скрыты. Поскольку в Posix нет локальных переменных, любое их поведение соответствует posix -.

readonlyвсегда определяет глобальные переменные. Локальные переменные только для чтения могут быть определены внутри функции с помощью local -rилиdeclare -r(ведут себя как localвнутри функций ).

Вы можете поправить свой скрипт, превратить все глобальные переменные в локальные *. Например, обернув все внутри main() { YOUR_SCRIPT_HERE; }; mainи заменив все readonlyнаlocal -r:

#! /usr/bin/env bash
main() {
  local -r x=constant
  declare -p x
  f() {
    local x=mutable1
    declare -p x
    x=mutable2
    declare -p x
  }
  f
  declare -p x
  # x=... would not work here
}
main

Конечно, вместо наивного исправления "обернуть весь скрипт внутри main" вы также можете определить свои функции снаружи mainдля лучшей структуры:

#! /usr/bin/env bash
main() {
  local -r x=constant
  declare -p x
  f
  declare -p x
  # x=... would not work here
}
f() {
  local x=mutable1
  declare -p x
  x=mutable2
  declare -p x
}
main

*Обратите внимание, что в обеих версиях main'sx(ранее глобальная переменная )находится в области видимости внутри fпри вызове из main. Поэтому локальные переменные внутри mainведут себя в основном как настоящие глобальные переменные. Механизм области видимости Bash немного необычен, если вы привыкли к области видимости, как в таких языках программирования, как C. Пример:

g() { local x=1; h; echo "g.x = $x"; }
h() { x=2; }
g
echo "global.x = $x";

… печатает

g.x = 2
global.x =
0
17.08.2020, 08:58

Теги

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