Pasar múltiples patrones de archivos a grep

Pasar múltiples patrones de archivos a grep

Tengo una secuencia de patrones de búsqueda almacenados en una matriz bash ( ptrn), que quiero pasar a un grepcomando. ¿Cómo puedo hacerlo?

  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

Respuesta1

¿Qué tal si damos los patrones a greptravés de un subnivel, por ejemplo:

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

Respuesta2

Dos opciones:

  • Manera compatible con los estándares: una los patrones con una nueva línea y proporciónelos como un solo argumento:

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

    (Esta característica está especificada porel estándar POSIX: "Ellista_patronesEl valor de consistirá en uno o más patrones separados por caracteres <nueva línea>...")

  • Manera no estándar, pero aún segura: cuando use un shell con matrices, como, por ejemplo, bash, cree una matriz de argumentos para grep:

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

    Esto está a salvo de la división de campos y la globalización y, en general, escómo se deben construir las líneas de comando a partir de variables.

Respuesta3

Si se garantiza que sus patrones/palabras almacenados como elementos de matriz no tendrán espacios ni caracteres especiales de shell sin escape, entonces puede usar bashla expansión del parámetro 'para pasar los elementos de la matriz grepcomo patrones individuales separados, por ejemplo, -e FN -e DS ...así:

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

O si pueden contener caracteres especiales de shell sin escape, puede crear expresiones regulares alrededor de |(o) (dividirse en todos los espacios también pero sin fallar) y usarlo con 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

O para preservar espacios exactos dentro de cada patrón de expresión regular pasando cada elemento de la matriz como un token individual y construyendo una expresión regular extendida de ellos usando |(lógico o), puedes hacer algo como esto:

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

información relacionada