Ось мій погляд на це.
Я краще не використовую 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
уникати розбиття слів на пробіли.
Функція не містить явних циклів, хоча внутрішньо прошиває кроки через вхідний масив для заповнення printf
. Формат printf використовує %q
для того, щоб уникнути вхідних даних таким чином, щоб їх можна було безпечно використовувати як ключі масиву.
$ a=("one two" three four)
$ array_contains a three && echo BOOYA
BOOYA
$ array_contains a two && echo FAIL
$
Зауважте, що все, що ця функція використовує, є вбудованою для удару, тому немає зовнішніх труб, які б тягнули вас вниз, навіть при розширенні команди.
І якщо вам не подобається використовувати eval
... ну, ви можете використовувати інший підхід. :-)