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ć if
instrukcję, ale nie wiem, jak jej używać grep
w skrypcie. Rozumiem, że grep
bę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 if
instrukcji. Pozbyłem się miejsca między, grep -q
a 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
[
…]
i to zadziała. Chociaż prawdopodobnie chcesz zacytować swój wzór:if grep -q "^$1" schemas.txt; then …
Odpowiedzi:
grep
zwraca inny kod wyjścia, jeśli coś znalazł (zero), a jeśli niczego nie znalazł (niezerowy). Wif
instrukcji zerowy kod wyjścia jest odwzorowany na „prawda”, a niezerowy kod wyjścia jest odwzorowany na fałsz. Ponadto grep ma-q
argument, 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:
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. (test
to to samo[
, z wyjątkiem zamknięcia]
)źródło
ls -l /usr/bin/\[
iman [
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żetype -all [
w bash.-q
, opcja ta mówi grepowi, aby był cichy (nie drukował dopasowanych linii).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ś:
źródło
grep -cim1
zamiast tego.Wiem, że się spóźniłem, ale uwielbiam tę krótką wersję:
źródło
Jeśli chcemy złapać pierwsze słowo pliku, musimy dodać
-zw
do grepBez
-z
dostajemy pierwsze słowo linii. Bez-w
otrzymujemy częściowe słowa.źródło
Jeśli chcesz go używać z nawiasami kwadratowymi, możesz wykonać poniższe czynności
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)
źródło
`grep -q PATTERN file.txt`
, w przeciwnym razie zastosowany zostanie operator split + glob, co spowodowałoby problem dla każdego wyniku zawierającego znaki$IFS
lub symbole wieloznaczne. Mówiąc bardziej ogólnie,[ "`cmd`" ]
zwróciłoby wartość true, jeślicmd
wypisuje 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. Podif cmd | grep -q .
tym względem preferowane może być użycie .-q
przełącznika jest stłumieniegrep
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[
(akatest
) z dokładnie jednym argumentem - mianowicie , -]
a następnie, ponieważ spowoduje to błąd, echo „nie znaleziono”. @ StéphaneChazelas, czy coś 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 tegoif grep -q PATTERN file.txt
chcesz.