Drucken Sie die Ausgabe erst, nachdem Sie das Muster gefunden haben


13

Es gibt ein Skript (nennen wir es echoer), das gedruckt wird, um eine Reihe von Informationen zu überprüfen. Ich möchte nur Linien sehen können, nachdem ein Muster gefunden wurde.

Ich stelle mir vor, wie eine Lösung aussehen könnte

echoer | solution_command <pattern>

Ideal patternwäre ein regulärer Ausdruck, aber harte Wertstrings würden für mich ausreichen.


Das Muster kann also aus mehreren Zeichenfolgen bestehen?
Inian

Ein Globus? Meinen Sie einen regulären Ausdruck? Globs sind nur für Dateinamenerweiterungen sinnvoll.
Terdon

@Inian Ich bin nicht sicher, ob ich die Frage verstehe. Wollen Sie fragen, ob dies mit Disjunktionen funktionieren soll?
user23146

Antworten:


21

AWK kann dies mit Musterbereichen tun, die die Verwendung eines beliebigen regulären Ausdrucks ermöglichen:

echoer | awk '/pattern/,0'

echoerDie Ausgabe wird beginnend mit der ersten übereinstimmenden Zeile gedruckt pattern.

AWK basiert auf Mustern und wird in der Regel mit einem solchen Ansatz verwendet, bei dem dieses Muster übereinstimmt. "Dieses Muster" kann ein Bereich von Mustern sein, definiert als "Wenn dieses Muster übereinstimmt, beginnen Sie damit, bis dieses andere Muster übereinstimmt". Dies wird durch Schreiben von zwei durch Komma getrennten Mustern wie oben angegeben. Muster können Textübereinstimmungen sein, wie in /pattern/, bei denen die aktuelle Zeile mit dem Muster verglichen und als regulärer Ausdruck interpretiert wird. Sie können auch allgemeine Ausdrücke sein, die für jede Zeile ausgewertet werden und als übereinstimmend gelten, wenn ihr Ergebnis nicht null oder nicht leer ist.

In AWK wird standardmäßig die aktuelle Zeile gedruckt.

Wenn Sie all dies zusammenfassen, wird awk '/pattern/,0'nach übereinstimmenden Zeilen gesucht. Wenn patternSie eine gefunden haben, wird die Standardaktion auf alle Zeilen angewendet, bis die 0Bedingung zutrifft (ungleich Null). awk '/pattern/,""'würde auch funktionieren.

Das Handbuch von Gawk geht viel detaillierter vor.


3
Mir war die Bereichssemantik mit Null als Ende des Bereichs nicht bekannt. Vielen Dank!
Kusalananda

@StephenKitt Das ist großartig! Was ist, wenn ich drucken wollte, bis es übereinstimmt 0? Wäre es /pattern/,/0/? Wie würde die Antwort aussehen, wenn Sie die Standardaktion explizit ausschreiben?
User23146

@ user23146 Ja, /pattern/,/0/würde drucken, bis eine Zeile (Datensatz) mit "0" gefunden wird. Das Schreiben des Snippets in die Antwort mit einer expliziten Aktion ergibt /pattern/,0 { print $0 }oder gleichwertig /pattern/,0 { print }.
Stephen Kitt

6

Das obligatorische sedÄquivalent zu @ StephenKitts awk:

sed '/pattern/,$!d'

patternEs wird wie in (im Gegensatz zu Extended Regular Expression in / / ) als regulärer Basisausdruck interpretiert . Einige Implementierungen haben eine Option (BSD, ast, aktuelles GNU / busybox, bald POSIX) oder (GNU, ssed, busybox, aktuelles BSD), um es stattdessen zu Extended Regular Expressions zu machen, und einige haben (ast) oder (ssed), um es zu machen ein perlartiger regulärer Ausdruck.grepawkegrepgrep -Esed-E-r-P-R

Mit perl:

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

4

mit GNU und * BSD grep:

grep -A1000000000 pattern file

Es sei denn, Ihre Datei enthält mehr als 1 Million Zeilen.


0

Wenn Sie einen Pager verwenden less, um die Ausgabe des Befehls anzuzeigen

less +pattern

0

awk für Zeilen nach (aber ohne) der ersten Musterübereinstimmung

Wenn die Zeile mit dem Triggermuster "CUT HERE" entspricht, können Sie sie in der gedruckten Ausgabe weglassen:

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

Jede Eingabezeile durchläuft zwei Komponenten im awk-Code. Die erste Komponente ist flag, was awk als "Drucken der Zeile, wenn die Variable flagungleich Null ist" interpretiert . Da awk-Variablen standardmäßig 0 sind, wird zunächst nichts gedruckt.

Die zweite Komponente /pattern/ { flag=1 }setzt das Flag auf 1, sobald es das Muster erkennt, und das Flag behält diesen Wert für den Rest des Laufs bei.

Zu dem Zeitpunkt, an dem das Muster zum ersten Mal erkannt wird, ist die Gelegenheit zum Drucken dieser Eingabezeile verstrichen. Alle nachfolgenden Zeilen (einschließlich zusätzlicher Zeilen, die das Muster enthalten) werden gedruckt.


0

Bash

Ein bisschen klobig, aber es funktioniert.

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

Diese Version catbasiert auf , ist aber einfacher zu verstehen.

#!/bin/bash
while IFS= read -r; do
    if [[ $REPLY =~ pattern ]]; then
        printf '%s\n' "$REPLY"
        break
    fi
done
cat
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.