Заимствуя у Денниса Уильямсона * answer , следующее решение объединяет массивы, безопасное для оболочки цитирование и регулярные выражения, чтобы избежать необходимости: повторять циклы;использование труб или других подпроцессов;или с использованием утилит не-bash.
declare -a array=('hello, stack' one 'two words' words last)
printf -v array_str -- ',,%q' "${array[@]}"
if [[ "${array_str},," =~ ,,words,, ]]
then
echo 'Matches'
else
echo "Doesn't match"
fi
Приведенный выше код работает с использованием регулярных выражений Bash для сопоставления со строковой версией содержимого массива.Есть шесть важных шагов, чтобы гарантировать, что совпадение с регулярным выражением не может быть одурачено умными комбинациями значений в массиве:
- Создайте строку сравнения, используя встроенную в Bash
printf
shell-цитирование %q
.Заключение в кавычки гарантирует, что специальные символы станут «безопасными для оболочки», если экранировать их с помощью обратной косой черты \
. - Выберите специальный символ, который будет служить разделителем значений.Разделитель ДОЛЖЕН быть одним из специальных символов, которые будут экранированы при использовании
%q
;это единственный способ гарантировать, что значения в массиве не могут быть построены умными способами, чтобы обмануть совпадение регулярного выражения.Я выбираю запятую ,
, потому что этот символ наиболее безопасен, когда eval'd или неправильно используется иным неожиданным образом. - Объедините все элементы массива в одну строку, используя два экземпляраспециальный символ, чтобы служить разделителем.Используя запятую в качестве примера, я использовал
,,%q
в качестве аргумента для printf
.Это важно, потому что два экземпляра специального символа могут появляться рядом друг с другом, только когда они появляются в качестве разделителя;все другие экземпляры специального символа будут экранированы. - Добавьте два завершающих экземпляра разделителя в строку, чтобы разрешить совпадения с последним элементом массива.Таким образом, вместо сравнения с
${array_str}
, сравните с ${array_str},,
. - Если искомая целевая строка предоставляется пользовательской переменной, вы должны экранировать все экземплярыспециальный символ с обратной косой чертой.В противном случае совпадение регулярного выражения становится уязвимым для того, чтобы его обманули искусно созданные элементы массива.
- Выполните совпадение регулярного выражения Bash со строкой.