将多个文件模式传递给 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如何通过子 shell提供模式,例如:

grep -f <(printf "%s\n" "${ptrn[@]}") FILE...

答案2

两个选项:

  • 符合标准的方式:用换行符连接模式并将其作为单个参数提供:

    grep -e "$(printf "%s\n" "${ptrn[@]}")" ...
    

    (此功能由POSIX 标准: “这模式列表的值应由一个或多个以 <newline> 字符分隔的模式组成...”)

  • 非标准但仍然安全的方式:当使用带有数组的 shell 时,例如 bash,构建一个参数数组以grep

    args=()
    for p in "${ptrn[@]}"
    do
       args+=(-e "$p")
    done
    grep "${args[@]}" ...
    

    这对于字段分割和通配符来说是安全的,并且一般来说如何根据变量构建命令行

答案3

如果保证作为数组元素存储的模式/单词中不包含空格或非转义的 shell 特殊字符,那么您可以使用的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

或者,如果它们可能包含非转义的 shell 特殊字符,则可以围绕|(或者)(在所有空间上分裂,但不会失败)并将其与以下内容一起使用:

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

相关内容