Передача нескольких шаблонов файлов в grep

Передача нескольких шаблонов файлов в grep

У меня есть последовательность шаблонов поиска, сохраненная в массиве 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

Связанный контент