Проблема в том, что когда я начал писать свой скрипт, я столкнулся с несколькими проблемами области действия переменных, что привело к появлению плохой привычки экспортировать почти все свои переменные.
Теперь, когда мой код стал довольно большим, я подумываю его почистить, и часть этого — удалить кучу бесполезных экспортов. К сожалению, я не уверен, что мои знания области видимости переменных полны. Даже после прочтения нескольких страниц на эту тему.
Что я знаю (и надеюсь, что это правда):
1. Экспорт переменной делает ее содержимое доступным для процессов подоболочки:
export myvar="content"
2-На то, что сделано в скобках, как это, повлияет удаление экспорта (насколько я понимаю, это единственный способ объявить/использовать подоболочку):
$(grep "content" <<< $myvar)
3. Переменные, объявленные без указания области действия, являются глобальными:
myvar="content"
4-Поскольку я не объявляю никаких локальных переменных, мне не нужно беспокоиться о возникновении проблем в моих функциях:
local myvar="i don't use this"
Вопросы:
1- Есть ли смысл продолжать удалять бесполезные экспорты, кроме моего кода, который не попахивает явным нубизмом?
2- Если я продолжу, есть ли что-то еще, о чем мне следует знать, что может повлиять на мой код и нарушить его? Или какие-то мои знания неверны/неполны?
3- Если вы знаете хорошо написанный (и полный) справочник по области действия переменных, пожалуйста, поделитесь ссылкой.
решение1
Вы можете удалить все экспорты без какого-либо эффекта на экспортируемые переменные, если только вы не используете export
дважды вычислять. Под дважды вычислять я подразумеваю:
var1=var2
export "${var1}=var3"
echo "$var2"
var3
Вместо этого просто используйте:
set -a
...в верхней части скрипта. Все переменные, определенные после этого, будут автоматически exported
- что будет включать переменные, которые вы могли не export
редактировать ранее. В качестве альтернативы вы можете только set -a
для части скрипта и позже set +a
отменить его - это также может работать как функция.
Но подоболочки в любом случае автоматически наследуют значения переменных, поэтому:
var1=value
( echo "$(echo "$var1")" )
value
export
В этом случае разницы нет.
Но если ваш скрипт вызывает другой скрипт или любой другой исполняемый файл, который интерпретирует значения, которые вы export
редактировали, и вы прекращаете export
их использовать, то эти значения больше не будут доступны в их среде. В следующем примере я использую переменную оболочки $PS1
, которая определяет содержимое приглашения интерактивной оболочки, чтобы продемонстрировать, как вариации export
переменных редактировали влияют на дочерние процессы.
export PS1="$(printf "this is another executable\n > ")"
echo exit | sh -i
###OUTPUT###
this is another executable
> exit
exit
Но ...
PS1="$(printf "this is another executable\n > ")"
echo exit | sh -i
###OUTPUT###
sh-4.3$ exit
exit
Но опять же, если вы явно объявляете переменные среды при вызове процесса...
PS1="$(printf "this is another executable\n > ")"
{
echo exit | PS1=$PS1 sh -i
echo exit | sh -i
}
###OUTPUT###
this is another executable
> exit
exit
sh-4.3$ exit
exit