Присвоение значения переменной в BASH
Вчера столкнулся с неожиданным (мной) поведением при присвоении значений переменным в BASH скрипте. Вот набросал пример, который воспроизводит проблему:
#!/bin/bash
function sep {
echo '------------------'
}
#блок 1
var1=`echo 1 ; echo 2 ; echo 3`
echo '1. var1=`echo 1 ; echo 2 ; echo 3`'
sep
echo '${var1}'
echo "${var1}"
sep
echo '${var1[*]}'
echo "${var1[*]}"
sep
echo '${var1[@]}'
echo "${var1[@]}"
sep
#блок 2
var1=()
var1+=( "A" )
var1+=( "B" )
var1+=( "C" )
echo '2. var1=() ....'
sep
echo '${var1}'
echo "${var1}"
sep
echo '${var1[*]}'
echo "${var1[*]}"
sep
echo '${var1[@]}'
echo "${var1[@]}"
sep
#блок 3
var1=`echo 1 ; echo 2 ; echo 3`
echo '3. var1=`echo 1 ; echo 2 ; echo 3`'
sep
echo '${var1}'
echo "${var1}"
sep
echo '${var1[*]}'
echo "${var1[*]}"
sep
echo '${var1[@]}'
echo "${var1[@]}"
sep
exit 0
Я ожидал что результат в третьем блоке будет как и в первом, но был удивлен - он отличается от первого и второго - вылезает хвост. Вот выхлоп
1. var1=`echo 1 ; echo 2 ; echo 3`
------------------
${var1}
1
2
3
------------------
${var1[*]}
1
2
3
------------------
${var1[@]}
1
2
3
------------------
2. var1=() ....
------------------
${var1}
A
------------------
${var1[*]}
A B C
------------------
${var1[@]}
A B C
------------------
3. var1=`echo 1 ; echo 2 ; echo 3`
------------------
${var1}
1
2
3
------------------
${var1[*]}
1
2
3 B C
------------------
${var1[@]}
1
2
3 B C
------------------
Я был уверен что второй
var1=
перезапишет старое значение переменной полностью, а оказалось что нет.
Не смог сформулировать запрос к гуглу чтоб найти описание такого поведения. Как правильно присваивать значение чтоб оно "затирало" предыдущее?echo 1 ; echo 2 ; echo 3
Ответы (1 шт):
У переменных в bash есть атрибуты. Они описаны в help declare (ну или в справке) и их можно посмотреть командой declare -p ПЕРЕМЕННАЯ.
Когда вы написали var1=() вы неявно задали переменной атрибут -a (array).
$ var1=()
$ declare -p var1
declare -a var1=()
Дальнейшая попытка написать var1=строка на самом деле изменяет первый элемент массива, что вы и наблюдаете в своём эксперименте.
Сделать переменную не массивом можно только полностью её удалив.
# попробуем убрать атрибут `array`
$ declare +a var1
bash: declare: var1: cannot destroy array variables in this way
# удаляем переменную
$ unset var1
# создаём заново
$ var1=string
$ declare -p var1
declare -- var1="string"
# теперь у неё нет никаких атрибутов
UPD: Документация https://www.gnu.org/software/bash/manual/html_node/Arrays.html