Есть хороший способ проверить, есть ли в массиве элемент в bash (лучше, чем циклически проходить)?
В качестве альтернативы, есть ли другой способ проверить, равно ли число или строка любому из набора предопределенных констант?
В Bash 4 вы можете использовать ассоциативные массивы:
# set up array of constants
declare -A array
for constant in foo bar baz
do
array[$constant]=1
done
# test for existence
test1="bar"
test2="xyzzy"
if [[ ${array[$test1]} ]]; then echo "Exists"; fi # Exists
if [[ ${array[$test2]} ]]; then echo "Exists"; fi # doesn't
Для первоначальной настройки массива вы также можете выполнить прямые назначения:
array[foo]=1
array[bar]=1
# etc.
или так:
array=([foo]=1 [bar]=1 [baz]=1)
${array[$test1]}
прост, но есть проблема: он не будет работать, если вы используетеset -u
в своих скриптах (что рекомендуется), так как вы получите «несвязанную переменную».set -u
: davidpashley.com/articles/writing-robust-shell-scripts.html , blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-one , openews.net/2012/bash- надежный сценарий для записи .Это старый вопрос, но я думаю, что самое простое решение еще не появилось
test ${array[key]+_}
. Пример:Выходы:
Чтобы увидеть, как это работает, проверьте это .
источник
env
чтобы избежать двусмысленности в псевдонимах, прогах и других функциях, которые могли принять название «тест». Как и вышеenv test ${xs[a]+_} && echo "a is set"
. Вы также можете получить эту функциональность, используя двойные скобки, тот же трюк и проверка на[[ ! -z "${xs[b]+_}" ]] && echo "b is set"
[[ ${xs[b]+set} ]]
Существует способ проверить, существует ли элемент ассоциативного массива (не установлен), это отличается от пустого:
Тогда используйте это:
источник
if ! some_check then return 1
=some_check
. Итак:isNotSet() { [[ ... ]] }
. Проверьте мое решение ниже, вы можете сделать это в простой проверке.Вы можете увидеть, присутствует ли запись, отправив содержимое массива в grep.
Вы также можете получить индекс записи с помощью grep -n, который возвращает номер строки совпадения (не забудьте вычесть 1, чтобы получить индекс, начинающийся с нуля). Это будет достаточно быстро, за исключением очень больших массивов.
объяснение:
$( ... )
то же самое, что использование обратных галочек для захвата вывода команды в переменнуюprintf
выводит mydata по одному элементу в строке@
вместо того, чтобы вместо*.
этого избегать разделения "привет мира" на 2 строки)grep
ищет точную строку:^
и$
соответствует началу и концу строкиgrep -n
возвращает строку № в виде 4: привет мирgrep -m 1
находит только первое совпадениеcut
извлекает только номер строкиКонечно, вы можете сложить вычитание в команду. Но тогда проверьте -1 на отсутствие:
$(( ... ))
делает целочисленную арифметикуисточник
Я не думаю, что вы можете сделать это правильно без циклов, если у вас нет очень ограниченных данных в массиве.
Вот один простой вариант, это правильно сказал бы, что
"Super User"
существует в массиве. Но это также сказал бы, что"uper Use"
находится в массиве.Проблема в том, что нет простого способа добавить якоря (о которых я могу думать), кроме циклического перемещения по массиву. Если вы не можете добавить их, прежде чем поместить их в массив ...
источник
grep "\b$FINDME\b"
). Вероятно, может работать с не алфавитно-цифровыми константами, которые не имеют пробелов, с"(^| )$FINDME(\$| )"
(или что-то в этом роде ... Мне никогда не удавалось узнать, что использует regexp grep.)источник
in_array
. Приветствия${ARRAY[@]}
следует использовать.