Jak sprawdzić, czy plik zawiera określony ciąg za pomocą Bash

265

Chcę sprawdzić, czy plik zawiera określony ciąg, czy nie w bash. Użyłem tego skryptu, ale nie działa:

 if [[ 'grep 'SomeString' $File' ]];then
   # Some Actions
 fi

Co jest nie tak w moim kodzie?

Hakim
źródło
Oto, jak command
grepować

Odpowiedzi:

465
if grep -q SomeString "$File"; then
  Some Actions # SomeString was found
fi

Nie potrzebujesz [[ ]]tutaj. Po prostu uruchom polecenie bezpośrednio. Dodaj -qopcję, gdy nie trzeba wyświetlać ciągu, gdy został znaleziony.

grepKomenda zwraca 0 lub 1 w kodzie wyjścia w zależności od wyniku wyszukiwania. 0 jeśli coś zostało znalezione; 1 inaczej.

$ echo hello | grep hi ; echo $?
1
$ echo hello | grep he ; echo $?
hello
0
$ echo hello | grep -q he ; echo $?
0

Możesz określić polecenia jako warunek if. Jeśli polecenie zwraca 0 w kodzie wyjścia, oznacza to, że warunek jest spełniony; inaczej fałszywe.

$ if /bin/true; then echo that is true; fi
that is true
$ if /bin/false; then echo that is true; fi
$

Jak widać, uruchamiasz tutaj programy bezpośrednio. Bez dodatkowych []lub [[]].

Igor Chubin
źródło
Więcej informacji na temat grepdostępnych opcji w asnwer stackoverflow.com/a/4749368/1702557
Paweł
2
może chcieć wziąć pod uwagę -Fxqparametry jak w stackoverflow.com/a/4749368/544721
Grzegorz Wierzowiecki
3
rozważ użycie -m 1w celu poprawy wydajności skanowania. Zwraca przy pierwszym wystąpieniu.
AlikElzin-kilaka
1
jeśli SomeStringzawiera wyrażenia regularne (np. .), możesz uzyskać nieoczekiwane wyniki. Bezpieczniej jest zawsze używać fgrep(lub grep -F) (chyba że naprawdę potrzebujesz wyrażenia regularnego, w którym to przypadku egrep(lub grep -E) jest prawdopodobnie najlepszym wyborem)
Walter Tross 27.04.18
Przykładowy ifprzykład jest niepoprawny, ponieważ sprawdza tylko, czy kod wyjścia nie jest zerem. Jeśli wystąpi jakikolwiek błąd, np. Nie można odczytać pliku, kod wyjścia również nie jest równy 0. Więc musisz zrobić coś takiego ec=$?i sprawdzić, czy to 0(znaleziono), a następnie, czy to 1(nie znaleziono), a następnie, czy jest to coś innego (błąd).
ddekany
40

Oprócz innych odpowiedzi, które mówiły ci, jak robić to, co chciałeś, próbuję wyjaśnić, co było nie tak (co chciałeś.

W Bash ifnależy wykonać polecenie. Jeśli kod wyjścia tego polecenia jest równy 0, wówczas thenczęść jest wykonywana, w przeciwnym elserazie część jest wykonywana.

Możesz to zrobić za pomocą dowolnego polecenia, jak wyjaśniono w innych odpowiedziach: if /bin/true; then ...; fi

[[to wewnętrzna komenda bash dedykowana do niektórych testów, takich jak istnienie pliku, porównania zmiennych. Podobnie [jest z zewnętrznym poleceniem (zwykle znajduje się w /usr/bin/[), które wykonuje z grubsza te same testy, ale potrzebuje ]ostatecznego argumentu, dlatego ]należy uzupełnić spacją po lewej stronie, co nie jest prawdą ]].

Tutaj nie musisz [[ani [.

Kolejną rzeczą jest sposób, w jaki cytujesz rzeczy. W bash jest tylko jeden przypadek, w którym pary cudzysłowów się zagnieżdżają "$(command "argument")". Ale w 'grep 'SomeString' $File'tobie masz tylko jedno słowo, ponieważ 'grep 'jest to cytowana jednostka, która jest łączona z, SomeStringa następnie ponownie łączona z ' $File'. Zmienna $Filenie jest nawet zastępowana jej wartością ze względu na użycie pojedynczych cudzysłowów. Właściwy sposób to zrobić grep 'SomeString' "$File".

Benoit
źródło
15

Jeśli chcesz sprawdzić, czy plik nie zawiera określonego ciągu, możesz to zrobić w następujący sposób.

if ! grep -q SomeString "$File"; then
  Some Actions # SomeString was not found
fi
Lahiru Chandima
źródło
10
##To check for a particular  string in a file

cd PATH_TO_YOUR_DIRECTORY #Changing directory to your working directory
File=YOUR_FILENAME  
if grep -q STRING_YOU_ARE_CHECKING_FOR "$File"; ##note the space after the string you are searching for
then
echo "Hooray!!It's available"
else
echo "Oops!!Not available"
fi
Nevin Raj Victor
źródło
2
Zmiana katalogu zwykle nie jest dobrym pomysłem (i tutaj jest całkowicie niepotrzebna, wystarczy zakwalifikować nazwę pliku do katalogu docelowego). I wtedy masz dokładnie to samo, co zaakceptowaną odpowiedź, tyle że z mniejszą ilością szczegółów.
Mat
Dzięki za radę Mat
Nevin Raj Victor
7

Najkrótsza (poprawna) wersja:

grep -q "something" file; [ $? -eq 0 ] && echo "yes" || echo "no"

można również zapisać jako

grep -q "something" file; test $? -eq 0 && echo "yes" || echo "no"

ale w tym przypadku nie trzeba tego jawnie testować, więc to samo z:

grep -q "something" file && echo "yes" || echo "no"
lzap
źródło
3
if grep -q something file; then echo yes; else echo no; fi. $?W ogóle nie ma powodu do bałaganu .
Charles Duffy
6

Jeśli chcesz sprawdzić, czy ciąg pasuje do całej linii, a jeśli jest to ciąg stały, możesz to zrobić w ten sposób

grep -Fxq [String] [filePath]

przykład

 searchString="Hello World"
 file="./test.log"
 if grep -Fxq "$searchString" $file
    then
            echo "String found in $file"
    else
            echo "String not found in $file"
 fi

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.)
Shubham Khatri
źródło
6
grep -q [PATTERN] [FILE] && echo $?

Status wyjścia ma wartość 0(prawda), jeśli wzorzec został znaleziony; w przeciwnym razie puste.

SupermanKelly
źródło
4
if grep -q [string] [filename]
then
    [whatever action]
fi

Przykład

if grep -q 'my cat is in a tree' /tmp/cat.txt
then
    mkdir cat
fi
użytkownik5854766
źródło
2

Spróbuj tego:

if [[ $(grep "SomeString" $File) ]] ; then
   echo "Found"
else
   echo "Not Found"
fi
vgokul129
źródło
3
Z wahaniem powstrzymuję się od głosowania za tym, ale przepełnienie stosu nie powinno utrwalać tego rodzaju logiki precla. grepzwraca bardzo dobry powód status wyjścia; przechwytywanie wyniku w ciągu może potencjalnie przechowywać dużą ilość tekstu w buforze, aby można było powiedzieć, że nie jest pusty.
tripleee
-1

Zrobiłem to, wydaje się, że działa dobrze

if grep $SearchTerm $FileToSearch; then
   echo "$SearchTerm found OK"
else
   echo "$SearchTerm not found"
fi
madarekrap
źródło
Cytowanie jest zepsute i prawdopodobnie chcesz uniknąć wyświetlania danych wyjściowych grep.
tripleee
-3
grep -q "something" file
[[ !? -eq 0 ]] && echo "yes" || echo "no"
chemila
źródło
1
Masz literówkę - !? ma być $?
lzap
... nie tylko ma to być $?, ale w ogóle nie ma takiej potrzeby - wystarczyif grep -q ...
Charles Duffy
1
Co więcej, foo && truthy_action || falsey_actionnie jest prawdziwym operatorem trójskładnikowym - jeśli truthy_actionzawiedzie, falsey_actionzostanie dodatkowo uruchomiony .
Charles Duffy
Mówiąc bardziej ogólnie, celem od ifjest uruchomienie komendy i sprawdzić jego kod wyjścia. Bardzo rzadko trzeba $?jawnie badać .
tripleee