2014-10-14 11 views
5

w skrypcie bash, mam listę linii w pliku pragnę grep a następnie wyświetlany na standardowe wyjście, które jest najłatwiej zrobić z jakimś czasie przeczytać:grep, inny komunikat Druk na żadnym meczów

grep "regex" "filepath" | while read line; do 
    printf "$line\n" 
done 

Chciałbym jednak poinformować użytkownika, że ​​grep nie dopasował żadnych linii. Wiem, że można to zrobić przez updating a variable inside the loop, ale wydaje się, że o wiele bardziej eleganckie podejście (jeśli to możliwe) byłoby próbą odczytania linii w pętli "do", a jeśli nie było wyjścia, mógłby zostać wyświetlony komunikat o błędzie.

To była moja pierwsza próba:

grep "regex" "filepath" | until [[ -z ${read line} ]]; do 
    if [[ -z $input ]]; then 
     printf "No matches found\n" 
     break 
    fi 
    printf "$line\n" 
done 

Ale w tym przypadku polecenie odczytu jest zniekształcone, a ja nie byłem pewien inny sposób wyrażenie kwerendy. Czy to podejście jest możliwe, a jeśli nie, czy istnieje bardziej odpowiednie rozwiązanie problemu?

+2

W twoim pierwszym przykładzie, tylko grep jest potrzebny i masz takie samo zachowanie. Czy jest to tylko przykład lub czy naprawdę chcesz to zrobić? – jordanm

+0

Czy to? Czy możesz pokazać, jak? Nadal jestem całkiem nowy, aby bashować i nie rozumiem, jak używać grep do tego zachowania. Kod, który napisałem, pokazuje wynik końcowy, który próbuję osiągnąć, by odpowiedzieć na twoje pytanie. Ah kot jest zbędny. Usunięto, dziękuję. – seraththundhuil

+0

grep domyślnie drukuje pasujące linie na standardowe wyjście, dlatego działająca pętla while/read czyta standardowe wejście. Po prostu uruchom 'grep 'regex" "filepath" 'i powinieneś zobaczyć swoje pasujące linie. –

Odpowiedz

13

Nie trzeba pętli w ogóle, jeśli chcesz po prostu wyświetli komunikat, gdy nie ma odpowiednika. Zamiast tego możesz użyć kodu powrotu grepa. Prosty if oświadczenie wystarczy:

if ! grep "regex" "filepath"; then 
    echo "no match" >&2 
fi 

To pokaże wyniki meczów grep (ponieważ to zachowanie domyślne grepa) i wyświetli komunikat o błędzie, jeśli nie robi.

Popularną alternatywą dla if ! jest użycie operatora ||. foo || bar można odczytać jako "do foo lub""lub" jeśli nie foo, a następnie bar ".

grep "regex" "filepath" || echo "no match" >&2 
1

Jak wspomniano w @jordanm, nie ma potrzeby stosowania pętli w przypadku użycia, o którym wspomniałeś.

output=$(grep "regex" "file") 
if [[ -n $output ]]; then 
    echo "$output" 
else 
    echo "Sorry, no results..." 
fi 

Jeśli trzeba iteracyjne nad wynikami dla przetwórstwa (raczej niż tylko wyświetlanie na standardowe wyjście), a następnie można zrobić coś takiego:

output=$(grep "regex" "file") 
if [[ -n $output ]]; then 
    while IFS= read -r line; do 
     # do something with $line 
    done <<< "$output" 
else 
    echo "Sorry, no results..." 
fi 

Metoda ta pozwala uniknąć stosując gazociąg lub powłoki w tle, tak aby wszelkie przypisania zmiennych wykonane w pętli będą dostępne dla reszty skryptu.

Ponadto, nie jestem pewien, czy to odnosi się do tego, co próbujesz w ogóle zrobić, ale grep ma możliwość ładowania wzorców z pliku (jeden na linię). Jest on wywoływany w następujący sposób:

grep search_target -f pattern_file.txt 
1

Odpowiedź Johna Kugelmana jest poprawna i zwięzła i należy ją przyjąć. Zajmuję się twoim pytaniem o składnię tutaj tylko dla kompletności.

Nie można użyć ${read line} do wykonania read - składnia klamry faktycznie oznacza (niejasno), że chcesz wartość zmiennej, której nazwa zawiera spację. Może strzelali do $(read line) ale tak naprawdę, to właściwy sposób napisać pętlę until będzie bardziej wzdłuż linii

grep "regex" "filepath" | until read line; [[ -z "$line" ]]; do 

... ale oczywiście, gdy nie ma wyjścia, rurociąg otrzyma żadnych linii , więc while i until są tutaj niepoprawne.

Warto przyłapać, że powodem, dla którego potrzebujesz osobnego do, jest możliwość posiadania wielu poleceń. Nawet coś podobnego do tego, co jest jeszcze bardziej tajemnicze, niż kiedykolwiek byś potrzebował. (W tym konkretnym przypadku, prawdopodobnie chciałbyś chcieć if, a nie while.)

Jak już zauważyłem, nie ma powodu, aby używać takiej pętli tutaj, ale chciałem uporządkować pytanie o to, jak napisać taką pętlę, ilekroć faktycznie takową chcesz.