Я новичок в сценариях Bash, у меня гораздо больше опыта работы с языками C-типа. Я написал несколько сценариев с условным условием, которое проверяет значение неинстанцированной переменной и, если она не существует или соответствует значению, устанавливает переменную. Кроме того, все это в цикле for. Что-то вроде этого:
for i in ${!my_array[@]}; do
if [ "${my_array[i]}" = true ]
then
#do something
else
my_array[i]=true;
fi
done
Это может привести к сбою через нулевой указатель в Java, так как my_array [i] не создается до тех пор, пока он не будет проверен. Это хорошая практика в Bash? Мой сценарий работает так, как я задумал, но я понял, что тот факт, что kluge работает сейчас, не означает, что он будет работать в будущем.
Благодарность!
2 ответа
По умолчанию ссылка на неопределенные (или «неустановленные») имена переменных в сценариях оболочки просто дает пустую строку. Но есть исключение: если оболочка запускается с опцией -u
или set -u
запускается в ней, расширения неустановленных переменных рассматриваются как ошибки и (если оболочка не является интерактивной) вызывают ее выйти. Bash также применяет этот принцип к элементам массива:
$ array=(zero one two)
$ echo "${array[3]}"
$ echo "array[3] = '${array[3]}'"
array[3] = ''
$ set -u
$ echo "array[3] = '${array[3]}'"
-bash: array[3]: unbound variable
Существуют также модификаторы, которые можно использовать для управления действиями расширения, если переменная (или элемент массива) не определена и / или пуста (определена как пустая строка):
$ array=(zero one '')
$ echo "array[2] is ${array[2]-unset}, array[3] is ${array[3]-unset}"
array[2] is , array[3] is unset
$ echo "array[2] is ${array[2]:-unset or empty}, array[3] is ${array[3]:-unset or empty}"
array[2] is unset or empty, array[3] is unset or empty
Существует множество других вариантов, см. стандарт синтаксиса оболочки POSIX, раздел 2.6.2 (Расширение параметров).
Кстати, вам нужно использовать фигурные скобки (как я делал выше) вокруг чего-либо, кроме простой ссылки на переменную. $name[2]
является ссылкой на обычную переменную name
(или элемент 0, если это массив), за которой следует строка "[2]"; ${name[2]}
, с другой стороны, является ссылкой на элемент 2 массива name
. Кроме того, вы почти всегда хотите обернуть ссылки на переменные в двойные кавычки (или включить их в строки в двойных кавычках), чтобы предотвратить «полезное» разбиение оболочки на слова и / или расширение их в списки соответствующих файлов. Например, этот тест:
if [ $my_array[i] = true ]
(в основном) эквивалентно:
if [ ${my_array[0]}[i] = true ]
... что совсем не то, что вы хотите. Но этот:
if [ ${my_array[i]} = true ]
Все еще не работает, потому что если my_array[i]
не установлен (или пуст), он расширится до эквивалента:
if [ = true ]
... это неверный синтаксис тестовых выражений. Вы хотите это:
if [ "${my_array[i]}" = true ]
вы найдете эту страницу по расширению параметров. полезно, а также этот по условностям.
Простой способ проверить переменную - проверить ее на ненулевую длину.
if [[ -n "$var" ]]
then : do stuff ...
Мне также нравится делать роковым доступ к несуществующей переменной; это означает дополнительную работу, но лучшую безопасность.
set -u # unset vars are fatal to access without exception handling
if [[ -n "${var:-}" ]] # handles unset during check
then : do stuff ...
Новые вопросы
bash
Для вопросов о скриптах, написанных для командной оболочки Bash. Для сценариев оболочки с ошибками / синтаксическими ошибками, пожалуйста, проверьте их с помощью программы shellcheck (или на сервере веб-проверки оболочки по адресу https://shellcheck.net) перед размещением здесь. Вопросы об интерактивном использовании Bash, скорее всего, будут касаться темы Super User, а не переполнения стека.