Übergeben mehrerer Dateimuster an grep

Übergeben mehrerer Dateimuster an grep

Ich habe eine Folge von Suchmustern in einem Bash-Array ( ptrn) gespeichert, die ich an einen Befehl übergeben möchte grep. Wie kann ich das tun?

  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

Antwort1

grepWie wäre es, die Muster über eine Unter-Shell weiterzugeben , zB:

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

Antwort2

Zwei Optionen:

  • Standardkonforme Vorgehensweise: Verbinde die Muster mit einer neuen Zeile und gib sie als einzelnes Argument an:

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

    (Diese Funktion wird angegeben durchder POSIX-Standard: "DerMusterlisteDer Wert muss aus einem oder mehreren durch <newline>-Zeichen getrennten Mustern bestehen ...")

  • Nicht standardmäßige, aber dennoch sichere Methode: Wenn Sie eine Shell mit Arrays verwenden, wie z. B. Bash, erstellen Sie ein Array von Argumenten für grep:

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

    Dies ist sicher vor Feldaufspaltung und Globbing und ist im Allgemeinenwie Befehlszeilen aus Variablen aufgebaut werden sollten.

Antwort3

Wenn Ihre als Array-Elemente gespeicherten Muster/Wörter garantiert keine Leerzeichen oder nicht maskierte Shell-Sonderzeichen enthalten, können Sie bashdie Parametererweiterung von verwenden, um die Array-Elemente grepals separate einzelne Muster zu übergeben, z. B. -e FN -e DS ...so:

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

Oder wenn sie nicht maskierte Shell-Sonderzeichen enthalten, können Sie die regulären Ausdrücke um |( herum aufbauen.oder) (Aufteilung auch auf allen Feldern, aber kein Fehler) und verwenden Sie es mit etwas wie:

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

Oder um die exakten Leerzeichen innerhalb jedes regulären Ausdrucksmusters beizubehalten, übergeben Sie jedes Array-Element als einzelnes Token und erstellen Sie daraus einen erweiterten regulären Ausdruck mithilfe von |(logisch oder), können Sie Folgendes tun:

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

verwandte Informationen