440 Stimmen

Wie testet man mit der Bash, ob ein String in einer Datei existiert?

Ich habe eine Datei, die Verzeichnisnamen enthält:

my_list.txt :

/tmp
/var/tmp

Ich möchte in der Bash prüfen, bevor ich einen Verzeichnisnamen hinzufüge, ob dieser Name bereits in der Datei existiert.

822voto

Thomas Punkte 160390
grep -Fxq "$FILENAME" my_list.txt

Der Exit-Status ist 0 (true), wenn der Name gefunden wurde, 1 (false), wenn nicht, also:

if grep -Fxq "$FILENAME" my_list.txt
then
    # code if found
else
    # code if not found
fi

Erläuterung

Hier sind die relevanten Abschnitte von die Manpage für grep :

grep [options] PATTERN [FILE...]

-F , --fixed-strings

        Interpretieren Sie PATTERN als eine Liste fester, durch Zeilenumbrüche getrennter Zeichenfolgen, von denen eine beliebige übereinstimmen soll.

-x , --line-regexp

        Wählen Sie nur die Treffer aus, die genau mit der gesamten Zeile übereinstimmen.

-q , --quiet , --silent

        Quiet; schreibt nichts auf die Standardausgabe. Sofortiges Beenden mit Status Null, wenn eine Übereinstimmung gefunden wird, auch wenn ein Fehler festgestellt wurde. Siehe auch die -s o --no-messages Option.

Fehlerbehandlung

Wie in den Kommentaren zu Recht hervorgehoben wurde, behandelt der obige Ansatz Fehlerfälle stillschweigend so, als ob die Zeichenfolge gefunden worden wäre. Wenn Sie Fehler anders behandeln wollen, müssen Sie die -q und erkennen Fehler anhand des Exit-Status:

Normalerweise ist der Exit-Status 0, wenn die ausgewählten Zeilen gefunden wurden, und 1, wenn nicht. Der Exit-Status ist jedoch 2, wenn ein Fehler aufgetreten ist, es sei denn, die -q o --quiet o --silent verwendet wird und eine ausgewählte Zeile gefunden wird. Beachten Sie jedoch, dass POSIX nur für Programme wie grep , cmp y diff dass der Exit-Status im Fehlerfall größer als 1 ist; daher ist es aus Gründen der Portabilität ratsam, eine Logik zu verwenden, die auf diese allgemeine Bedingung statt auf strikte Gleichheit mit 2 prüft.

Zur Unterdrückung der normalen Ausgabe von grep können Sie ihn umleiten auf /dev/null . Beachten Sie, dass der Standardfehler ungerichtet bleibt, so dass alle Fehlermeldungen, die grep auf der Konsole ausgeben, wie Sie es sich wahrscheinlich wünschen würden.

Um die drei Fälle zu behandeln, können wir eine case Erklärung:

case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
  0)
    # code if found
    ;;
  1)
    # code if not found
    ;;
  *)
    # code if an error occurred
    ;;
esac

109voto

Kuf Punkte 16424

Bezüglich der folgenden Lösung:

grep -Fxq "$FILENAME" my_list.txt

Falls Sie sich (wie ich) fragen sollten, was -Fxq bedeutet in einfachem Englisch:

  • F : Beeinflusst die Interpretation von PATTERN (fester String anstelle eines Regex)
  • x : Ganze Zeile abgleichen
  • q : Schhhhh... Minimaldruck

Aus der man-Datei:

-F, --fixed-strings
    Interpret  PATTERN  as  a  list of fixed strings, separated by newlines, any of which is to be matched.
    (-F is specified by POSIX.)
-x, --line-regexp
    Select only those matches that exactly match the whole line.  (-x is specified by POSIX.)
-q, --quiet, --silent
    Quiet; do not write anything to standard output.  Exit immediately with zero status  if  any  match  is
          found,  even  if  an error was detected.  Also see the -s or --no-messages option.  (-q is specified by
          POSIX.)

51voto

Luca Borrione Punkte 15697

Meiner Meinung nach gibt es drei Methoden:

1) Kurzer Test für einen Namen in einem Pfad (ich bin mir nicht sicher, ob dies Ihr Fall ist)

ls -a "path" | grep "name"

2) Kurzer Test für eine Zeichenkette in einer Datei

grep -R "string" "filepath"

3) Längeres Bash-Skript mit Regex:

#!/bin/bash

declare file="content.txt"
declare regex="\s+string\s+"

declare file_content=$( cat "${file}" )
if [[ " $file_content " =~ $regex ]] # please note the space before and after the file content
    then
        echo "found"
    else
        echo "not found"
fi

exit

Dies sollte sein Schneller wenn Sie um mehrere Zeichenfolgen in einer Datei zu testen Inhalt mit Hilfe einer Schleife, z. B. durch Ändern der Regex an jedem beliebigen Punkt.

31voto

Christian737 Punkte 401

Der einfachste und leichteste Weg wäre der:

isInFile=$(cat file.txt | grep -c "string")

if [ $isInFile -eq 0 ]; then
   #string not contained in file
else
   #string is in file at least once
fi

grep -c zeigt an, wie oft die Zeichenkette in der Datei vorkommt.

24voto

imwilsonxu Punkte 2852

Einfacher geht es nicht:

if grep "$filename" my_list.txt > /dev/null
then
   ... found
else
   ... not found
fi

Tipp: Senden an /dev/null wenn Sie den Exit-Status des Befehls, aber nicht die Ausgaben haben wollen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X