У меня есть последовательность шаблонов поиска, сохраненная в массиве bash ( ptrn
), которую я хочу передать команде grep
. Как это сделать?
ptrn=("FN" "DS")
for fl in "$@"; do # loop through number of files
if [[ -f "$fl" ]]; then
printf '\n%s%s%s\n\n' "$mgn" "==> $flnm <==" "$rst"
grep --color "$ptrn" "$flnm"
fi
done
решение1
Как насчет передачи шаблонов grep
через дочернюю оболочку, например:
grep -f <(printf "%s\n" "${ptrn[@]}") FILE...
решение2
Два варианта:
Способ, соответствующий стандартам: Объедините шаблоны с помощью новой строки и укажите его как один аргумент:
grep -e "$(printf "%s\n" "${ptrn[@]}")" ...
(Эта функция указанастандарт POSIX: "список_образцовзначение должно состоять из одного или нескольких шаблонов, разделенных символами <newline> ...")
Нестандартный, но все еще безопасный способ: при использовании оболочки с массивами, например, bash, создайте массив аргументов для
grep
:args=() for p in "${ptrn[@]}" do args+=(-e "$p") done grep "${args[@]}" ...
Это безопасно от разделения полей и подстановки, и в целомкак командные строки должны быть построены из переменных.
решение3
Если ваши шаблоны/слова, хранящиеся в виде элементов массива, гарантированно не содержат пробелов или неэкранированных специальных символов оболочки, то вы можете использовать bash
расширение параметра , чтобы передать элементы массива grep
как отдельные индивидуальные шаблоны, например, -e FN -e DS ...
так:
ptrn=("FN" "DS")
# Prepend "-e" to each array element
ptrn2="${ptrn[@]/#/-e }"
# Don't quote "$ptrn2" or it will be passed as a single token and wouldn't work.
grep --color $ptrn2 file
Или, если они могут содержать неэкранированные специальные символы оболочки, вы можете построить регулярные выражения вокруг |
(или) (разделяя также на все пространства, но не терпя неудачу) и использовать его с чем-то вроде:
ptrn=("FN" "DS")
# Translate spaces " " single or multiple including spaces between words in a single array element into "|".
ptrn2="$(echo ${ptrn[@]} | tr " " "|")"
# -E enables extended regular expressions ... needed for this to work.
grep --color -E "$ptrn2" file
Или сохранить точные пробелы внутри каждого шаблона регулярного выражения, передавая каждый элемент массива как отдельный токен и создавая из них расширенное регулярное выражение с помощью |
(логический или), вы можете сделать что-то вроде этого:
ptrn=("FN" "DS")
# Append "|" to each array element.
ptrn2="$(printf '%s|' "${ptrn[@]}")"
# Delete the last character i.e. the extra "|".
ptrn2="${ptrn2::-1}"
# -E enables extended regular expressions ... needed for this to work.
grep --color -E "$ptrn2" file