Вот мой взгляд на это.
Я бы предпочел не использовать цикл для bash, если я могу избежать этого, так как для этого требуется время. Если что-то должно зацикливаться, пусть это будет что-то написанное на языке более низкого уровня, чем сценарий оболочки.
function array_contains { # arrayname value
local -A _arr=()
local IFS=
eval _arr=( $(eval printf '[%q]="1"\ ' "\${$1[@]}") )
return $(( 1 - 0${_arr[$2]} ))
}
Это работает путем создания временного ассоциативного массива, _arr
индексы которого получены из значений входного массива. (Обратите внимание, что ассоциативные массивы доступны в bash 4 и выше, поэтому эта функция не будет работать в более ранних версиях bash.) Мы установили$IFS
чтобы избежать разбиения слов в пробелах.
Функция не содержит явных циклов, хотя внутренняя часть bash проходит через входной массив для заполнения printf
. Формат printf используется %q
для гарантии того, что входные данные экранированы, чтобы их можно было безопасно использовать в качестве ключей массива.
$ a=("one two" three four)
$ array_contains a three && echo BOOYA
BOOYA
$ array_contains a two && echo FAIL
$
Обратите внимание, что все, что использует эта функция, является встроенным в bash, поэтому нет никаких внешних каналов, тянущих вас вниз, даже в расширении команды.
И если вам не нравится eval
... ну, вы можете использовать другой подход. :-)