Gute Möglichkeit
Normalerweise können Sie dies nicht mit grep tun, aber Sie können andere Tools verwenden. AWK wurde bereits erwähnt, kann aber auch sed
wie folgt verwendet werden:
sed -e '1p' -e '/youpattern/!d'
Wie es funktioniert:
Das Dienstprogramm Sed arbeitet in jeder Zeile einzeln und führt für jede Zeile bestimmte Befehle aus. Sie können mehrere Befehle haben und mehrere -e
Optionen angeben. Wir können jedem Befehl einen Bereichsparameter voranstellen, der angibt, ob dieser Befehl auf eine bestimmte Zeile angewendet werden soll oder nicht.
"1p" ist ein erster Befehl. Es wird ein p
Befehl verwendet, der normalerweise alle Zeilen druckt. Wir stellen ihm jedoch einen numerischen Wert voran, der den Bereich angibt, auf den er angewendet werden soll. Hier verwenden wir 1
die erste Zeile. Wenn Sie mehr Zeilen drucken möchten, können Sie angeben, x,yp
wo x
die erste Zeile gedruckt werden y
soll und wo die letzte Zeile gedruckt werden soll. Um beispielsweise die ersten 3 Zeilen zu drucken, würden Sie verwenden1,3p
Der nächste Befehl d
löscht normalerweise alle Zeilen aus dem Puffer. Vor diesem Befehl setzen wir yourpattern
zwischen zwei /
Zeichen. Dies ist der andere Weg (zuerst mussten wir angeben, welche Zeilen wir mit dem p
Befehl ausgeführt haben) , um die Zeilen zu adressieren, auf denen der Befehl ausgeführt werden soll. Dies bedeutet, dass der Befehl nur für die übereinstimmenden Zeilen funktioniert yourpattern
. Es wird jedoch ein !
Zeichen vor dem d
Befehl verwendet, der seine Logik umkehrt. Jetzt werden alle Linien entfernt, die nicht mit dem angegebenen Muster übereinstimmen.
Am Ende druckt sed alle im Puffer verbleibenden Zeilen. Wir haben jedoch Zeilen aus dem Puffer entfernt, die nicht übereinstimmen, sodass nur übereinstimmende Zeilen gedruckt werden.
Zusammenfassend: Wir drucken die erste Zeile und löschen dann alle Zeilen, die nicht zu unserem Muster passen, aus der Eingabe. Die restlichen Zeilen werden gedruckt (also nur die Zeilen, die dem Muster entsprechen).
Problem in der ersten Zeile
Wie in den Kommentaren erwähnt, liegt bei diesem Ansatz ein Problem vor. Wenn das angegebene Muster auch mit der ersten Zeile übereinstimmt, wird es zweimal gedruckt (einmal per p
Befehl und einmal aufgrund einer Übereinstimmung). Wir können dies auf zwei Arten vermeiden:
1d
Befehl hinzufügen nach 1p
. Wie bereits erwähnt, d
löscht der Befehl Zeilen aus dem Puffer und wir geben den Bereich durch Nummer 1 an, was bedeutet, dass nur die erste Zeile gelöscht wird. Der Befehl wäre alsosed -e '1p' -e '1d' -e '/youpattern/!d'
Verwenden des 1b
Befehls anstelle von 1p
. Es ist ein Trick. b
Befehl ermöglicht es uns, zu einem anderen Befehl zu springen, der durch eine Beschriftung angegeben ist (auf diese Weise können einige Befehle weggelassen werden). Wenn dieses Label nicht angegeben wird (wie in unserem Beispiel), springt es nur zum Ende der Befehle und ignoriert den Rest der Befehle für unsere Zeile. In unserem Fall entfernt der letzte d
Befehl diese Zeile nicht aus dem Puffer.
Vollständiges Beispiel:
ps aux | sed -e '1b' -e '/syslog/!d'
Semikolon verwenden
Bei einigen sed
Implementierungen können Sie Tipparbeit sparen, indem Sie Befehle durch Semikolon trennen, anstatt mehrere -e
Optionen zu verwenden. Wenn Sie sich also nicht dafür interessieren, portabel zu sein, wäre der Befehl ps aux | sed '1b;/syslog/!d'
. Es funktioniert zumindest in GNU sed
und busybox
Implementierungen.
Verrückter Weg
Hier ist jedoch ein ziemlich verrückter Weg, dies mit grep zu tun. Es ist definitiv nicht optimal, ich poste dies nur zu Lernzwecken, aber Sie können es zum Beispiel verwenden, wenn Sie kein anderes Tool in Ihrem System haben:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog'
Wie es funktioniert
Zunächst verwenden wir die -n
Option, um Zeilennummern vor jeder Zeile hinzuzufügen. Wir wollen alle Zeilen nummerieren, die wir abgleichen .*
- alles, auch leere Zeilen. Wie in den Kommentaren vorgeschlagen, können wir auch mit '^' übereinstimmen, das Ergebnis ist dasselbe.
Dann verwenden wir erweiterte reguläre Ausdrücke, damit wir \|
Sonderzeichen verwenden können, die als ODER funktionieren. Wir passen also an, ob die Zeile mit 1:
(erste Zeile) beginnt oder unser Muster enthält (in diesem Fall sein syslog
).
Zeilennummern Problem
Jetzt ist das Problem, wir bekommen diese hässlichen Zeilennummern in unserer Ausgabe. Wenn dies ein Problem ist, können wir sie folgendermaßen entfernen cut
:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog' | cut -d ':' -f2-
-d
Diese Option gibt das Trennzeichen und die zu -f
druckenden Felder (oder Spalten) an. Wir wollen also jede Zeile eines jeden :
Zeichens ausschneiden und nur die 2. und alle nachfolgenden Spalten drucken. Dadurch wird die erste Spalte mit ihrem Begrenzer effektiv entfernt, und genau das ist erforderlich.
ack
so nützlich sind, und warumperl
geschnellt Vergangenheitsed
,awk
etc. in der Popularität: Es ist wichtig , dass die Teile zu einem kohärenten Ganzen zusammenzufassen.