Jak sprawdzić, czy w pliku Bash istnieje ciąg znaków?


Odpowiedzi:


655
grep -Fxq "$FILENAME" my_list.txt

Status wyjścia to 0 (prawda), jeśli nazwa została znaleziona, 1 (fałsz), jeśli nie, więc:

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

Wyjaśnienie

Oto odpowiednie sekcje strony podręcznika dlagrep :

grep [options] PATTERN [FILE...]

-F, --fixed-strings

        Interpretuj WZÓR jako listę stałych ciągów, oddzielonych znakami nowej linii, z których każda ma zostać dopasowana.

-x, --line-regexp

        Wybierz tylko te dopasowania, które dokładnie pasują do całej linii.

-q, --quiet,--silent

        Cichy; nie pisz niczego na standardowe wyjście. Wyjdź natychmiast ze statusem zero, jeśli zostanie znalezione dopasowanie, nawet jeśli wykryty zostanie błąd. Zobacz także opcję -slub --no-messages.

Obsługa błędów

Jak słusznie wskazano w komentarzach, powyższe podejście po cichu traktuje przypadki błędów tak, jakby ciąg został znaleziony. Jeśli chcesz obsługiwać błędy w inny sposób, musisz pominąć tę -qopcję i wykryć błędy na podstawie stanu wyjścia:

Zwykle stan wyjścia wynosi 0, jeśli zostaną znalezione wybrane linie, a w przeciwnym razie 1. Ale stan wyjścia to 2, jeśli wystąpił błąd, chyba że użyto opcji -qlub --quietlub --silenti znaleziono wybraną linię. Należy jednak pamiętać, że tylko POSIX mandaty dla programów takich jak grep, cmporaz diff, że stan wyjście w przypadku błędu być większa niż 1; dlatego zaleca się, ze względu na przenośność, zastosować logikę, która sprawdza ten ogólny warunek zamiast ścisłej równości z 2.

Aby stłumić normalne wyjście grep, możesz przekierować je na /dev/null. Zauważ, że standardowy błąd nie jest przekierowywany, więc wszelkie komunikaty o błędach, które grepmogą zostać wydrukowane, trafią na konsolę, tak jak zapewne chcesz.

Aby obsłużyć trzy przypadki, możemy użyć caseinstrukcji:

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

2
Jeśli wykonam to polecenie ze skryptu bash, jak złapać 0 lub 1 do zmiennej?
Toren

6
@Toren Najnowszy status wyjścia można uzyskać za pomocą $?. możesz także użyć polecenia grep obok ifinstrukcji (jak pokazano w zaktualizowanej odpowiedzi).
Shawn Chin

5
Możesz używać grep -Fqx "$FILENAME"i nie musisz się martwić o wyrażenia regularne w treści zmiennej i nie będziesz musiał ich używać w ciągu wyszukiwania.
Wstrzymano do odwołania.

4
Kilka uwag dla ludzi, którzy patrzą na tę odpowiedź: 1) W bash 0 zawsze jest prawdziwe, a wszystko inne zawsze jest fałszywe 2) Używaj flagi -x tylko wtedy, gdy chcesz, aby cała linia dokładnie pasowała. Jeśli chcesz tylko sprawdzić, czy Twój ciąg w ogóle istnieje w pliku, zostaw to. Jeśli chcesz sprawdzić, czy łańcuch istnieje dokładnie, ale niekoniecznie dopasowuje całą linię (tj. Jako całe słowo), użyj -w.
Schmick

1
Nie rozumiem, czy -q / --silentjest to potrzebne? Fałszywie mówi „wszystko dobre”, aby walić, nawet jeśli wystąpi błąd. Jeśli dobrze to zrozumiałem. Wydaje się, że w tej sprawie jest błędna koncepcja.
redanimalwar

90

W odniesieniu do następującego rozwiązania:

grep -Fxq "$FILENAME" my_list.txt

Jeśli zastanawiasz się (tak jak ja), co -Fxqoznacza zwykły angielski:

  • F: Wpływa na sposób interpretacji WZORCA (stały ciąg zamiast wyrażenia regularnego)
  • x: Dopasuj całą linię
  • q: Ciii… minimalne drukowanie

Z pliku man:

-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.)

5
-F nie wpływa na przetwarzanie pliku, wpływa na interpretację WZORCA. Zazwyczaj WZÓR jest interpretowany jako wyrażenie regularne, ale z -F będzie interpretowany jako stały ciąg.
Adam S

41

Trzy metody w mojej głowie:

1) Krótki test nazwy na ścieżce (nie jestem pewien, czy to może być twój przypadek)

ls -a "path" | grep "name"


2) Krótki test na ciąg znaków w pliku

grep -R "string" "filepath"


3) Dłuższy skrypt bashowy, używając wyrażenia regularnego:

#!/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

Powinno to być szybsze, jeśli trzeba przetestować wiele ciągów znaków na zawartości pliku za pomocą pętli, na przykład zmieniając wyrażenie regularne w dowolnym wierszu.


10
Dlaczego potrzebne są spacje przed i po $ file_contenet?
EminezArtus

Plus 1 za szybkie i bardziej ogólne rozwiązanie
Wassadamo,

19

Prostszy sposób:

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

Wskazówka: wyślij, /dev/nulljeśli chcesz status wyjścia polecenia, ale nie wyjścia.


1
lub użyj -qtego samego, co --quiet:)
rogerdpack

zgadzam się -qrównież na najlepszą odpowiedź tutaj i jest czwarte miejsce. brak sprawiedliwości na tym świecie.
tatsu

14

Najłatwiejszym i najprostszym sposobem byłoby:

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 zwróci liczbę, ile razy łańcuch występuje w pliku.


5

Jeśli dobrze zrozumiałem twoje pytanie, powinno zrobić to, czego potrzebujesz.

  1. możesz określić katalog, który chcesz dodać poprzez zmienną $ check
  2. jeśli katalog znajduje się już na liście, wynikiem jest „katalog już wymieniony”
  3. jeśli katalog nie znajduje się jeszcze na liście, jest dołączany do my_list.txt

W jednej linii :check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt


Nie musisz testować wyjścia grep, możesz po prostu użyć grep -qgrep i wywołać go bezpośrednio, ifjak robi to Thomas w swojej odpowiedzi. Ponadto pytanie nie obejmowało sprawdzenia, czy katalog istnieje przed dodaniem go do listy (w końcu może to być lista usuniętych katalogów).
sorpigal

Usunąłem przykładowy skrypt, który nie dodał niczego do odpowiedzi udzielonej przez Thomasa.
lecodesportif,

3

Jeśli chcesz tylko sprawdzić istnienie jednej linii, nie musisz tworzyć pliku. Na przykład,

if grep -xq "LINE_TO_BE_MATCHED" FILE_TO_LOOK_IN ; then
  # code for if it exists
else
  # code for if it does not exist
fi  

3

Moja wersja używa fgrep

  FOUND=`fgrep -c "FOUND" $VALIDATION_FILE`
  if [ $FOUND -eq 0 ]; then
    echo "Not able to find"
  else
    echo "able to find"     
  fi  

Nie widzę -copcji wfgrep --help
Nam G VU

3
grep -E "(string)" /path/to/file || echo "no match found"

-E opcja powoduje, że grep używa wyrażeń regularnych


1

Rozwiązanie @ Thomas z jakiegoś powodu nie działało, ale miałem dłuższy ciąg znaków specjalnych i białych znaków, więc zmieniłem tylko następujące parametry:

if grep -Fxq 'string you want to find' "/path/to/file"; then
    echo "Found"
else
    echo "Not found"
fi

Mam nadzieję, że to komuś pomoże



0
grep -Fxq "String to be found" | ls -a
  • grep pomoże ci sprawdzić zawartość
  • Ls wyświetli wszystkie pliki

@ThomWiggers Próbowałem tego samego i zadziałało to dla mnie.
Shinoy Shaji

-1
if grep -q "$Filename$" my_list.txt
   then
     echo "exist"
else 
     echo "not exist"
fi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.