Локальные переменные в bash:локальный против подоболочки
Вопрос
Насколько я знаю, существует два способа создания локальных переменных в функции bash:создайте подоболочку или объявите каждую переменную локальной.
Например:
# using local
function foo
{
local count
for count in $(seq 10)
do
echo $count
done
}
или
# using subshell
function foo
{
(
for count in $(seq 10)
do
echo $count
done
)
}
Очевидно, что версию, использующую подоболочку, проще написать, потому что вам не нужно заботиться об объявлении всех локальных переменных (не говоря уже о переменных (среды), созданных/экспортируемых такими инструментами, как получить).Но я мог себе представить, что создание подоболочки требует дополнительных затрат.
Так какой же подход лучше?Каковы плюсы/минусы?
Решение
Создание подоболочки включает в себя fork()
, поэтому у него определенно есть накладные расходы по сравнению с локальной переменной.Хотя субоболочки дешевы (вы не беспокоитесь об их стоимости, когда они вам нужны), они не бесплатны.
Если ваш скрипт будет интенсивно использоваться и производительность действительно имеет значение (поэтому сотни пользователей будут запускать его одновременно, много раз в день), тогда вы можете беспокоиться о стоимости производительности подоболочки.OTOH, если вы запускаете его раз в месяц, а сценарий в целом выполняется менее 10 секунд, вы, вероятно, этого не сделаете.
Однако с точки зрения ясности гораздо лучше быть явным и объявить переменные — это снижает риск поломки скрипта, потому что кто-то придет и скажет: «Эта подоболочка явно не нужна» (и это действительно не нужно). т;Я бы хотел удалить подоболочки из ваших функций).
Посмотрите на эволюцию сценариев Perl.Они начинались как всеобщие переменные, возникающие по требованию.Постепенно они стали более строгими, и теперь обычным стилем является предварительное объявление всех переменных.В какой-то степени оболочки пошли по тому же пути, но не так строго, как Perl.Awk также представляет собой интересный пример;его функции используют глобальные переменные, если только они не являются аргументами функции, что приводит к написанию функций с 3 активными аргументами (скажем) и 5 неактивными аргументами, которые эффективно определяют локальные переменные.Это немного эксцентрично, хотя и «работает».
Другие советы
Теперь, убедившись, что все функции всегда объявляют все переменные как местные, довольно сложно.
Я думаю, что это очень распространено и предпочитает всегда использовать функции подпунктов:
f() (
echo "we are a subshell"
)
Нет необходимости объявлять локальные переменные - но и никакой способ изменить глобальные переменные. Что хорошо, на мой взгляд!
Одним из дополнительных последствий, что вам всегда нужно проверить код возврата / выхода из таких функций и действовать соответственно! Это, потому что вы не можете выйти из вас скрипт из функции подпунктов!
f() (
echo "Trying to exit"
exit 1
)
f
echo "Did not exit"
Это не выйдет на ваш скрипт. Вы должны сделать это таким образом:
f() (
echo "Trying to exit"
exit 1
)
f || exit $?
echo "Did not exit"
Это выйдет