Wydrukuj tylko po znalezieniu wzoru


13

Istnieje skrypt (nazwijmy go echoer), który drukuje, aby przejrzeć mnóstwo informacji. Chciałbym widzieć linie tylko po znalezieniu wzoru.

Wyobrażam sobie zastosowanie rozwiązania, które mogłoby wyglądać podobnie

echoer | solution_command <pattern>

Idealnie patternbyłoby wyrażenie regularne, ale ciągi twardej wartości byłyby dla mnie wystarczające.


Więc wzór może składać się z wielu ciągów?
Inian

Glob? Masz na myśli wyrażenie regularne? Globs mają sens tylko w przypadku rozszerzeń nazw plików.
terdon

@Inian Nie jestem pewien, czy rozumiem pytanie. Czy chcesz zapytać, czy chcę, aby działało to z zakłóceniami?
user23146,

Odpowiedzi:


21

AWK może to zrobić z zakresami wzorców, co pozwala na użycie dowolnego wyrażenia regularnego:

echoer | awk '/pattern/,0'

wypisze echoerwyjście, zaczynając od dopasowania pierwszego wiersza pattern.

AWK jest oparte na wzorcach i jest zwykle używane z podejściem typu „jeśli ten wzór pasuje, zrób to”. „Ten wzór” może być zakresem wzorów, zdefiniowanym jako „kiedy ten wzór pasuje, zacznij to robić, aż ten inny wzór się dopasuje”; jest to określone przez napisanie dwóch wzorów oddzielonych przecinkiem, jak powyżej. Wzory mogą być dopasowanymi tekstami, tak jak w /pattern/przypadku, gdy bieżący wiersz jest sprawdzany względem wzorca, interpretowany jako wyrażenie regularne; mogą być również wyrażeniami ogólnymi, ocenianymi dla każdego wiersza i uznanymi za zgodne, jeśli ich wynik jest niezerowy lub niepusty.

W AWK domyślną akcją jest wydrukowanie bieżącej linii.

Łącząc to wszystko, awk '/pattern/,0'szuka linii pasujących pattern, a gdy je znajdzie, stosuje domyślną akcję do wszystkich linii, dopóki 0warunek się nie zgadza (jest różny od zera). awk '/pattern/,""'też by działał.

Podręcznik Gawk jest o wiele bardziej szczegółowy.


3
Nie byłem świadomy semantyki zakresu z zerą jako końcem zakresu. Dzięki!
Kusalananda

@StephenKitt To jest świetne! Co jeśli chciałbym drukować, dopóki nie będzie pasował 0? Czy by to /pattern/,/0/bylo Jak wyglądałaby odpowiedź jednoznacznie zapisująca akcję domyślną?
user23146,

@ użytkownik23146 tak, /pattern/,/0/drukowałby, dopóki nie znajdzie linii (rekordu) zawierającego „0”. Zapisanie fragmentu w odpowiedzi za pomocą jawnej akcji daje /pattern/,0 { print $0 }lub równoważnie /pattern/,0 { print }.
Stephen Kitt

7

Obowiązkowy sedodpowiednik @ StephenKitt awk:

sed '/pattern/,$!d'

patternjest interpretowane jako podstawowe wyrażenie regularne jak w grep(w przeciwieństwie do rozszerzonego wyrażenia regularnego w awk/ egrep/ grep -E). Niektóre sedimplementacje mają opcję -E(BSD, ast, ostatnie GNU / busybox, wkrótce POSIX) lub -r(GNU, ssed, busybox, niektóre ostatnie BSD), aby zamiast tego rozszerzyć wyrażenia regularne, a niektóre mają -P(ast) lub -R(ssed), aby to zrobić wyrażenie regularne podobne do perla.

Z perl:

perl -ne 'print if /pattern/ .. undef'

4

z GNU i * BSD grep:

grep -A1000000000 pattern file

O ile plik nie zawiera więcej niż 1 mln linii, to wszystko.


0

Jeśli używasz pagera, na przykład lessdo wyświetlania danych wyjściowych polecenia

less +pattern

0

awk dla linii po pierwszym dopasowaniu wzorca (ale bez niego)

Jeśli linia zawierająca wzorzec wyzwalający jest odpowiednikiem „CUT HERE”, możesz pominąć go na wydruku:

echoer | awk 'flag ; /pattern/ { flag=1 }'

Każdy wiersz danych wejściowych przebiega przez dwa składniki w kodzie awk. Pierwszym składnikiem jest flag, który awk interpretuje jako „wypisz linię, jeśli zmienna flagjest niezerowa”. Ponieważ zmienne awk mają domyślnie wartość 0, początkowo nic nie wydrukuje.

Drugi składnik, /pattern/ { flag=1 }ustawia flagę na 1, gdy tylko wykryje wzorzec, a flaga zachowuje tę wartość do końca cyklu.

Do czasu pierwszego wykrycia wzoru minęła możliwość wydrukowania tego wiersza wprowadzania. Zostaną wydrukowane wszystkie kolejne wiersze (w tym dodatkowe wiersze zawierające wzór).


0

Grzmotnąć

Trochę niezgrabne, ale działa.

#!/bin/bash
found=false
while IFS= read -r; do
    if $found || [[ $REPLY =~ pattern ]]; then
        found=true
        printf '%s\n' "$REPLY"
    fi
done

Ta wersja polega na cat, ale jest łatwiejsza do zrozumienia.

#!/bin/bash
while IFS= read -r; do
    if [[ $REPLY =~ pattern ]]; then
        printf '%s\n' "$REPLY"
        break
    fi
done
cat
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.