В Bourne-подобной оболочке, которая поддерживает переменную массива, мы можем использовать некоторый анализ, чтобы проверить, является ли переменная массивом.
Все команды ниже были выполнены после запуска a=(1 2 3)
.
zsh
:
$ declare -p a
typeset -a a
a=( 1 2 3 )
bash
:
$ declare -p a
declare -a a='([0]="1" [1]="2" [2]="3")'
ksh93
:
$ typeset -p a
typeset -a a=(1 2 3)
pdksh
и его производная:
$ typeset -p a
set -A a
typeset a[0]=1
typeset a[1]=2
typeset a[2]=3
yash
:
$ typeset -p a
a=('1' '2' '3')
typeset a
Пример в bash
:
if declare -p var 2>/dev/null | grep -q 'declare -a'; then
echo array variable
fi
Этот подход - слишком много работы и должен порождать подоболочку. Использование другой встроенной оболочки, такой как =~
in [[ ... ]]
, не требует вложенной оболочки , но все еще слишком сложно.
Есть ли более простой способ выполнить эту задачу?
Ответы:
Я не думаю, что вы можете, и я не думаю, что это на самом деле имеет значение.
Это делает то же самое в любом из
ksh93
иbash
. Похоже, что, возможно, все переменные являются массивами в этих оболочках или, по крайней мере, любой обычной переменной, которой не были назначены специальные атрибуты, но я не проверял большую часть этого.В
bash
ручных переговорах о различных поведениях для массива по сравнению с строковым переменным при использовании+=
заданий, но потом изгородь и утверждает , что массив только ведут себя по- разному в компаунде контекста назначения.В нем также говорится, что переменная считается массивом, если какой-либо нижний индекс был присвоен значение - и явно включает в себя возможность нулевой строки. Выше вы можете видеть, что регулярное назначение определенно приводит к назначению нижнего индекса - и поэтому я предполагаю, что все это массив.
Практически, возможно, вы можете использовать:
... чтобы точно определить набор переменных, которым был присвоен только один индекс со значением 0.
источник
${a[1]-not array}
может ли сделать задачу, не так ли?bash
руководством: переменная массива считается установленной, если подстрочный индекс был присвоен значение. Нулевая строка является допустимым значением. Если какой-либо нижний индекс назначен, его массив для спецификации. На практике также нет, потому что вы можете сделатьa[5]=x
. Я думаю,[ 1 -eq "${#a[@]}" ] && [ -n "${a[0]+1}" ]
может сработать.Таким образом, вы действительно хотите только среднюю часть
declare -p
без мусора вокруг этого?Вы можете написать макрос, такой как:
так что вы можете сделать:
(Простая функция не сработает, если вы захотите использовать ее для локальных переменных функции).
С псевдонимами
источник
alias vartype="$VARTYPE"
... или просто не определял$VARTYPE
вообще - это должно работать, верно? вам нужна только этаshopt
вещь,bash
потому что она не соответствует спецификацииalias
расширения в скриптах.В зш
источник
echo ${(t)var}
, проще. Спасибо за это.Чтобы проверить переменную var, с
Можно проверить, существует ли более одного индекса массива:
Если первое значение индекса не равно нулю:
Единственная трудная путаница - это когда существует только одно значение индекса, а это значение равно нулю (или единице).
Для этого условия можно использовать побочный эффект от попытки удалить элемент массива из переменной, которая не является массивом:
Это работает правильно для Bash:
Для zsh индекс может быть равен 1 (если не активен совместимый режим).
Подоболочка необходима, чтобы избежать побочного эффекта стирания индекса 0 переменной var.
Я не нашел способа заставить его работать в ksh.
Редактировать 1
Эта функция работает только в bash4.2 +
Редактировать 2
Это также работает только для bash4.2 +
Примечание. Это даст ложные срабатывания, если var содержит проверенные строки.
источник
( unset "var[0]" 2>/dev/null; ) && echo "var is an array."
правильно сообщает, что var - это массив, если переменная установлена вvar=()
массив с нулевыми элементами. Это действует точно так же, как объявить.grep -E
вместо того,grep -P
чтобы избежать зависимости от GNU grep.-a
, как это:declare -airl var='()'
. Поэтому тест grep будет работать .Для bash это немного хак (хотя и задокументировано): попытка использовать
typeset
для удаления атрибута «массив»:(Вы не можете сделать это в
zsh
, это позволяет вам преобразовывать массив в скаляр,bash
поскольку это явно запрещено.)Так:
Или в функции, отмечая предостережения в конце:
Обратите внимание на использование
typeset -g
(bash-4.2 или новее), это требуется внутри функции, чтобыtypeset
(syn.declare
) Не работалоlocal
и не затирало значение, которое вы пытаетесь проверить. Это также не обрабатывает «переменные» типы функций, вы можете добавить другой тест ветвления, используяtypeset -f
при необходимости.Другой (почти полный) вариант - использовать это:
Однако есть одна небольшая проблема: массив с одним индексом 0 соответствует двум из указанных выше условий. Это то, на что ссылается mikeserv, bash на самом деле не имеет жестких различий, и некоторые из них (если вы посмотрите журнал изменений) можно обвинить в ksh и совместимости с тем, как
${name[*]}
или${name[@]}
ведут себя не-массивы.Таким образом, частичное решение:
Я использовал в прошлом вариант этого:
это тоже нуждается в подоболочке.
Еще один, возможно, полезный метод
compgen
:При этом будут перечислены все проиндексированные массивы, однако ассоциативные массивы не обрабатываются специально (до bash-4.4) и отображаются как обычные переменные (
compgen -A variable
).источник
typeset +a
Также сообщает об ошибке в KSH. Не в зш, хотя.Короткий ответ:
Для двух оболочек, которые ввели это обозначение (
bash
иksh93
) скалярная переменная - это просто массив с одним элементом .Ни одному из них не нужно специальное объявление для создания массива. Достаточно только назначения, а простое назначение
var=value
идентичноvar[0]=value
.источник
bash -c 'unset var; var=foo; typeset -p var'
. Ответ bash сообщает о массиве (нужен -a)? Теперь сравните с:bash -c 'unset var; var[12]=foo; typeset -p var'
. Почему есть разница? A: Оболочка поддерживает (хорошо или плохо) представление о том, какие переменные являются скалярами или массивами. Оболочка ksh смешивает обе концепции в одну.Встроенная в
array
yash опция имеет несколько опций, которые работают только с переменными массива. Пример:-d
опция сообщит об ошибке в переменной, не являющейся массивом:Таким образом, мы можем сделать что-то вроде этого:
Этот подход не будет работать, если переменная массива доступна только для чтения . Попытка изменить переменную только для чтения, приводящую к ошибке:
источник
источник