Frage sed oder awk: lösche n Zeilen nach einem Muster


Wie würde ich Muster und numerische Bereiche in sed (oder einem ähnlichen Werkzeug - awk zum Beispiel) mischen? Ich möchte bestimmte Zeilen in einer Datei abgleichen und die nächsten n Zeilen löschen, bevor ich fortfahre, und das möchte ich als Teil einer Pipeline machen.


75
2017-12-09 10:05


Ursprung


Antworten:


Ich werde es versuchen.

So löschen Sie 5 Zeilen nach einem Muster (einschließlich der Linie mit dem Muster):

sed -e '/pattern/,+5d' file.txt

So löschen Sie 5 Zeilen nach einem Muster (ohne die Linie mit dem Muster):

sed -e '/pattern/{n;N;N;N;N;d}' file.txt

130
2017-12-09 12:56



Einfach awk Lösungen:

Angenommen, der reguläre Ausdruck, der zum Suchen übereinstimmender Zeilen verwendet werden soll, wird in der Shell-Variablen gespeichert $regexund die Anzahl der Zeilen zum Überspringen $count.

Wenn die passende Zeile sollte ebenfalls übersprungen werden ($count + 1 Zeilen werden übersprungen):

... | awk -v regex="$regex" -v count="$count" \
  '$0 ~ regex { skip=count; next } --skip >= 0 { next } 1'

Wenn die passende Zeile sollte nicht übersprungen werden ($count Linien nach das Spiel wird übersprungen):

... | awk -v regex="$regex" -v count="$count" \
  '$0 ~ regex { skip=count; print; next } --skip >= 0 { next } 1'

Erläuterung:

  • -v regex="$regex" -v count="$count" definiert awk Variablen basierend auf Schale Variablen mit dem gleichen Namen.
  • $0 ~ regex entspricht der Linie von Interesse
    • { skip=count; next } initialisiert die Anzahl der Überspringungen und geht zur nächsten Zeile über, wobei die passende Zeile übersprungen wird; in der zweiten Lösung, die print Vor next stellt sicher, dass es ist nicht übersprungen.
    • --skip >= 0 dekrementiert den Überspringungszähler und führt eine Aktion aus, wenn (noch)> = 0 ist, was bedeutet, dass die betreffende Zeile übersprungen werden sollte.
    • { next } geht zur nächsten Zeile über und überspringt so effektiv die aktuelle Zeile
  • 1 ist eine gebräuchliche Abkürzung für { print }; Das heißt, die aktuelle Zeile wird einfach gedruckt
    • Nur nicht übereinstimmende und nicht übersprungene Zeilen erreichen diesen Befehl.
    • Der Grund dass 1 ist äquivalent zu { print } ist das 1 wird als ein boolesches Muster interpretiert, das definitionsgemäß immer als wahr ausgewertet wird, was bedeutet, dass die zugehörige Aktion (Block) unbedingt ausgeführt wird. Da ist es Nein assoziierte Aktion in diesem Fall, awk standardmäßig auf Drucken die Linie.

4
2018-05-20 17:57



Mit dieser Lösung können Sie "n" als Parameter übergeben und Ihre Muster aus einer Datei lesen:

awk -v n=5 '
    NR == FNR {pattern[$0]; next}
    {
        for (patt in pattern) {
            if ($0 ~ patt) {
                print # remove if you want to exclude a matched line
                for (i=0; i<n; i++) getline
                next
            }
        }
        print
    }
' file.with.patterns -

Die Datei mit dem Namen "-" bedeutet stdin für awk, also ist dies für Ihre Pipeline geeignet


2
2017-12-09 15:17



Dies könnte für Sie funktionieren:

cat <<! >pattern_number.txt
> 5 3
> 10 1
> 15 5
> !
sed 's|\(\S*\) \(\S*\)|/\1/,+\2{//!d}|' pattern_number.txt |
sed -f - <(seq 21)
1 
2
3
4
5
9
10
12
13
14
15
21

2
2018-01-20 12:20