Czy grep zwraca true / false lub czy istnieją alternatywne metody


130

W ramach tego skryptu muszę być w stanie sprawdzić, czy pierwszy podany argument pasuje do pierwszego słowa pliku. Jeśli tak, wyjdź z komunikatem o błędzie; jeśli nie, dołącz argumenty do pliku. Rozumiem, jak napisać ifinstrukcję, ale nie wiem, jak jej używać grepw skrypcie. Rozumiem, że grepbędzie to wyglądać mniej więcej tak

grep ^$1 schemas.txt

Wydaje mi się, że powinno to być znacznie łatwiejsze niż robię.

Występuje błąd „zbyt wiele argumentów” w ifinstrukcji. Pozbyłem się miejsca między, grep -qa następnie wystąpił błąd, którego oczekiwał operator binarny.

if [ grep -q ^$1 schemas.txt ]
then
        echo "Schema already exists. Please try again"
        exit 1
else
        echo "$@" >> schemas.txt
fi

1
Strać []i to zadziała. Chociaż prawdopodobnie chcesz zacytować swój wzór:if grep -q "^$1" schemas.txt; then …
derobert

jedno liniowe rozwiązanie wykorzystujące funkcję „Group Command” Basha: stackoverflow.com/questions/6550484/...
Trevor Boyd Smith

Odpowiedzi:


186

grepzwraca inny kod wyjścia, jeśli coś znalazł (zero), a jeśli niczego nie znalazł (niezerowy). W ifinstrukcji zerowy kod wyjścia jest odwzorowany na „prawda”, a niezerowy kod wyjścia jest odwzorowany na fałsz. Ponadto grep ma -qargument, aby nie wyświetlać dopasowanego tekstu (ale zwraca tylko kod statusu wyjścia)

Możesz więc użyć grep w następujący sposób:

if grep -q PATTERN file.txt; then
    echo found
else
    echo not found
fi

Krótko if [ -z "$var" ]…mówiąc , kiedy robisz coś podobnego , okazuje się, że [tak naprawdę to polecenie , które wykonujesz, tak jak grep. W moim systemie to jest /usr/bin/[. (Cóż, technicznie rzecz biorąc, twoja powłoka prawdopodobnie ma ją wbudowaną, ale jest to optymalizacja. Zachowuje się, jakby była poleceniem). Działa w ten sam sposób, [zwraca zero kodu wyjścia dla true, a niezerowy kod wyjścia dla false. ( testto to samo [, z wyjątkiem zamknięcia ])


Dlaczego instrukcja if nie potrzebuje nawiasów? Mam to działa bez, ale nie rozumiem dlaczego. Czy nadal mogę go zagnieżdżać bez wsporników?
Lauren

@Lauren, przegapiłeś krótką notatkę? [nie jest częścią składni if, jest (koncepcyjnie) uruchamianym poleceniem, tak jak grep
derobert

2
@Lauren Nie używasz grep wewnątrz [, używasz jednego lub drugiego, w zależności od tego, jaki warunek chcesz sprawdzić. (Możesz użyć dowolnego polecenia w if, btw, jeśli po prostu sprawdza kod wyjścia.)… Cóż, myślę, że prawdopodobnie wymyślisz powód, aby użyć grep wewnątrz [, ale byłby to dość skomplikowany skrypt i jego nie jest to normalne.
derobert

3
Do Twojej wiadomości, uruchom ls -l /usr/bin/\[i man [zobacz, że [jest to program jak każdy inny, po prostu wygląda jak element składniowy - to powinno uczynić go oczywistym i łatwiejszym do zrozumienia. (dla wygody [jest także wbudowany w bash, myślnik i inne - ale wciąż jest to polecenie). spróbuj także type -all [w bash.
cas

1
@AlexanderCska, jeśli chcesz, aby grep wydrukował dopasowane linie (np. Aby gdzieś je potokować), a następnie pomiń -q, opcja ta mówi grepowi, aby był cichy (nie drukował dopasowanych linii).
derobert

47

Innym prostym sposobem jest użycie grep -c.

Dane wyjściowe (nie zwracane jako kod wyjścia), liczba wierszy pasujących do wzorca, więc 0, jeśli nie ma dopasowania, lub 1 lub więcej, jeśli istnieje dopasowanie.

Tak więc, jeśli chcesz sprawdzić, czy wzór jest dopasowany 3 lub więcej razy, zrobiłbyś:

if [ "$(grep -c "^$1" schemas.txt)" -ge 3 ]; then
  ...

17
Dokładniej, wyświetli 1, jeśli zostanie znaleziony tylko raz. Aby wyświetlić 1, niezależnie od liczby znalezionych dopasowań, użyj grep -cim1zamiast tego.
manatwork

Tej metody można także użyć do rozróżnienia błędu grep od grep „wzorzec znaleziony 0 razy”. (choć nie z dokładną instrukcją if, myślę, że wymagana jest zmienna)
Evan Benn

3

Wiem, że się spóźniłem, ale uwielbiam tę krótką wersję:

grep -q ^$1 schemas.txt && echo "Schema already exists. Please try again" || echo "$@" >> schemas.txt

0

Jeśli chcemy złapać pierwsze słowo pliku, musimy dodać -zwdo grep

if grep -qzw "^$1" file
then 
   ... 
else 
   ... 
fi

Bez -zdostajemy pierwsze słowo linii. Bez -wotrzymujemy częściowe słowa.


-2

Jeśli chcesz go używać z nawiasami kwadratowymi, możesz wykonać poniższe czynności

if [ `grep -q PATTERN file.txt` ]; then
    echo found
else
    echo not found

Ta logika działa dla wszystkich poleceń, po prostu umieść swoje polecenia w backstick (przycisk powyżej karty lub na dół Esc lub na lewo od 1 przycisku)


1
Musiałbyś zacytować `grep -q PATTERN file.txt`, w przeciwnym razie zastosowany zostanie operator split + glob, co spowodowałoby problem dla każdego wyniku zawierającego znaki $IFSlub symbole wieloznaczne. Mówiąc bardziej ogólnie, [ "`cmd`" ]zwróciłoby wartość true, jeśli cmdwypisuje co najmniej jedną niepustą linię na stdout (z potencjalnymi problemami, jeśli wypisze bajty NUL). Oznacza to, że powłoka będzie musiała przechowywać całe dane wyjściowe w pamięci i czekać na zakończenie. Pod if cmd | grep -q .tym względem preferowane może być użycie .
Stéphane Chazelas

To polecenie nie miałoby żadnego sensu. Celem -qprzełącznika jest stłumienie grep sygnału wyjściowego. Mówisz: Sprawdź PATTERN w pliku.txt, pomiń wszelkie dane wyjściowe, a następnie ustaw status zwracany zgodnie z tym, czy PATTERN został znaleziony. Następnie zignoruj status zwracany, weź wyjście z polecenia (które musieliśmy być puste), zastosuj dzielenie słów i rozszerzanie globu plików (nie powodując żadnych argumentów), a następnie uruchom polecenie [(aka test) z dokładnie jednym argumentem - mianowicie , - ]a następnie, ponieważ spowoduje to błąd, echo „nie znaleziono”. @ StéphaneChazelas, czy coś przeoczyłem?
Wildcard

1
@Wildcard, masz rację, najwyraźniej przeoczyłem -q. Ten komentarz miałby sens [ `grep PATTERN file.txt ` ], ale jak wskazano w komentarzu, [ "`grep -n PATTERN file.txt`" ]byłoby lepiej, gdyby WZORZEC mógł dopasować tylko puste linie. Chociaż tutaj oczywiście tego if grep -q PATTERN file.txtchcesz.
Stéphane Chazelas
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.