Passando vários padrões de arquivo para grep

Passando vários padrões de arquivo para grep

Eu tenho uma sequência de padrões de pesquisa armazenados em um array bash ( ptrn), que desejo passar para um grepcomando. Como eu posso fazer isso?

  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

Responder1

Que tal fornecer os padrões grepatravés de um sub-shell, por exemplo:

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

Responder2

Duas opções:

  • Maneira compatível com os padrões: junte os padrões com nova linha e forneça-os como argumento único:

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

    (Este recurso é especificado poro padrão POSIX: "Olista_padrãoO valor de deve consistir em um ou mais padrões separados por caracteres <nova linha> ...")

  • Maneira não padrão, mas ainda segura: ao usar um shell com matrizes, como, por exemplo, bash, crie uma matriz de argumentos para grep:

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

    Isso é protegido contra divisão de campo e globulação e, em geral, écomo as linhas de comando devem ser construídas a partir de variáveis.

Responder3

Se for garantido que seus padrões/palavras armazenados como elementos da matriz não contenham espaços ou caracteres especiais de shell sem escape, você poderá usar a bashexpansão do parâmetro para passar os elementos da matriz grepcomo padrões individuais separados, -e FN -e DS ...por exemplo:

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

Ou se eles contiverem caracteres especiais de shell sem escape, você poderá criar expressões regulares em torno de |(ou) (dividindo em todos os espaços também, mas não falhando) e use-o com algo como:

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

Ou para preservar espaços exatos dentro de cada padrão de expressão regular, passando cada elemento da matriz como um token individual e construindo uma expressão regular estendida deles usando o |(lógico ou), você pode fazer algo assim:

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

informação relacionada