Angenommen, ein einfaches Grep wie:
$ psa aux | grep someApp
1000 11634 51.2 0.1 32824 9112 pts/1 SN+ 13:24 7:49 someApp
Dies liefert viele Informationen, aber da die erste Zeile des Befehls ps fehlt, gibt es keinen Kontext für die Informationen. Ich würde es vorziehen, wenn auch die erste Zeile von ps angezeigt wird:
$ psa aux | someMagic someApp
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
1000 11634 51.2 0.1 32824 9112 pts/1 SN+ 13:24 7:49 someApp
Natürlich könnte ich einen regulären Ausdruck für grep speziell für ps hinzufügen:
$ ps aux | grep -E "COMMAND|someApp"
Ich würde jedoch eine allgemeinere Lösung vorziehen, da es andere Fälle gibt, in denen ich auch die erste Zeile haben möchte.
Dies scheint ein guter Anwendungsfall für einen "stdmeta" -Dateideskriptor zu sein .
bash
command-line
dotancohen
quelle
quelle
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.-C
Argument to verwenden,ps
und Sie müssten es nicht in grep umleiten. zBps u -C someApp
oder sogarps u -C app1 -C app2 -C app3
ps aux | { head -1; grep foo; }
von @Nahuel Fouilleul (dies ist wahrscheinlich die einzige Lösung, an die ich mich bei Bedarf sofort erinnern kann)Antworten:
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: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 wir1
die erste Zeile. Wenn Sie mehr Zeilen drucken möchten, können Sie angeben,x,yp
wox
die erste Zeile gedruckt werdeny
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 wiryourpattern
zwischen zwei/
Zeichen. Dies ist der andere Weg (zuerst mussten wir angeben, welche Zeilen wir mit demp
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 funktioniertyourpattern
. Es wird jedoch ein!
Zeichen vor demd
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 nach1p
. 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 von1p
. 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 letzted
Befehl diese Zeile nicht aus dem Puffer.Vollständiges Beispiel:
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 Befehlps aux | sed '1b;/syslog/!d'
. Es funktioniert zumindest inGNU sed
undbusybox
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:
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 mit1:
(erste Zeile) beginnt oder unser Muster enthält (in diesem Fall seinsyslog
).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
:-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.quelle
cat -n
werden und würde klarer aussehen als mit einem Grep, der dafür missbraucht wird.nl
Zählt keine leeren Zeilen (sondern druckt sie ohne Zeilennummer),cat -n
formatiert die Nummerierung mit vorangestellten Leerzeichen, entfernt überhauptgrep -n .
leere Zeilen und fügt einen Doppelpunkt hinzu. Alle haben ihre ... äh ... Funktionen ;-)ps aux | sed '1p;/pattern/!d'
druckt die erste Zeile zweimal, wenn sie mit dem Muster übereinstimmt . Am besten ist das zu verwendendeb
Befehl:ps aux | sed -e 1b -e '/pattern/!d'
.cat -n
ist nicht POSIX.grep -n '^'
würde jede Zeile nummerieren (kein Problem für ps-Ausgaben ohne Leerzeilen).nl -ba -d $'\n'
nummeriert jede Zeile.1b;...
weder portierbar noch POSIX-fähig ist. Nach "b" kann kein anderer Befehl angegeben werden. Sie benötigen daher eine neue Zeile oder einen anderen -e-Ausdruck.Wie stehst du zu "
awk
statt"grep
?NR == 1
: Anzahl der Datensätze == 1; dh die erste Zeile||
: oder:/syslogd/
: Zu suchendes MusterEs könnte sich auch lohnen, sich das anzuschauen
pgrep
, obwohl dies eher für Skripte als für benutzerbezogene Ausgaben gedacht ist. Es wird jedoch vermieden, dass dergrep
Befehl selbst in der Ausgabe angezeigt wird.quelle
EDIT: nach Kommentaren
Ich
head -1
würde zwar alle Eingaben lesen, aber nach dem Testen funktioniert es auch.Ausgabe ist
quelle
{ IFS='' read line; ... }
falls der Header mit Leerzeichen beginnt.head -1
anstelle der Lese / Echo-Combo verwenden.head -n1
meiner Bash. Dies kann wahrscheinlich implementierungsspezifisch sein. Mein Kopf liest in diesem Fall nicht die gesamte Eingabe, sondern nur die erste Zeile, und der Rest verbleibt im Eingabepuffer.head -n1
ist kürzer, aber es sieht so aus, als ob sogar die POSIX-Spezifikation nicht angibt, wie viel von ihrer Eingabe gelesen werden darf, sodass sie möglicherweiseread line; echo $line
doch portabler ist.Ps unterstützen internen Filter,
Angenommen, Sie suchen nach einem Bash-Prozess:
ps -C bash -f
Listet alle Prozesse mit dem Namen auf
bash
.quelle
Ich neige dazu, den Header an stderr zu senden :
Dies ist in der Regel ausreichend für menschliche Lesezwecke. z.B:
Der in Klammern gesetzte Teil kann zur allgemeinen Verwendung in ein eigenes Skript eingefügt werden.
Ein zusätzlicher Vorteil besteht darin, dass die Ausgabe weiter geleitet werden kann (zu
sort
usw.) und der Header oben bleibt.quelle
Sie könnten auch
tee
und verwendenhead
:Beachten Sie jedoch, dass dieser Ansatz eine Problemumgehung erfordert, um zuverlässig zu sein , solange Signale
tee
nicht ignoriertSIGPIPE
werden können (siehe z. B. die Diskussion hier ). Die Problemumgehung besteht darin, SIGPIPE-Signale zu ignorieren. Dies kann beispielsweise in bash-ähnlichen Shells erfolgen:Beachten Sie auch, dass die Ausgabereihenfolge nicht garantiert wird .
quelle
grep
:| { sleep .5; cat }
.Vielleicht
ps
wären zwei Befehle am einfachsten.quelle
ps aux
Anruf ändern könnte ... Und wenn Sie nur diese statische erste Zeile wollen, warum nicht manuell wiederholen?Sie könnten pidstat verwenden mit:
Beispiel:
Weitere Informationen: http://linux.die.net/man/1/pidstat
quelle
Fügen Sie Folgendes zum Testen zuerst in Ihre .bashrc-Datei ein oder kopieren / fügen Sie es in die Shell ein.
Verwendung: psls [grep pattern]
Stellen Sie sicher, dass Sie Ihre .bashrc-Datei (oder .bash_profile, wenn Sie sie stattdessen dort ablegen) als Quelle angeben:
Die Funktion wird sogar in der Shell-Befehlszeile automatisch vervollständigt. Wie Sie in einer anderen Antwort angegeben haben, können Sie die erste Zeile an eine Datei weiterleiten, um einen Anruf in ps zu speichern.
quelle
psl
, die nurps
und jeweilsgrep
einmal aufruft (und nicht benötigthead
).sortiere aber behalte die Kopfzeile oben
Und benutze es so
quelle
Vor allem dank Janis Papanagnou in comp.unix.shell benutze ich folgende Funktion:
Dies hat eine Reihe von Vorteilen:
-i
für Übereinstimmungen ohne-E
Berücksichtigung der Groß- und Kleinschreibung, für erweiterte reguläre Ausdrücke usw.Anwendungsbeispiel:
quelle
Ein anderer Weg mit
gnu ed
:oder, wenn die Shell die Prozessersetzung unterstützt:
das ist:
Tragbarer, ohne
gnu
'!'
oder durch Shell-Substitution - Verwenden Sie nur dieed
integrierte Funktion, um die Ausgabe von in den Pufferr
zur
lesen,ps aux
und löschen Sie dann nicht übereinstimmende Zeilen im2,$
Bereich, und drucken Sie das Ergebnis aus:Und da die
sed
Befehle in der akzeptierten Antwort auch die selbst passende Zeile ausgeben, mit einemsed
, der unterstützt,-f-
und einer Shell, die die Prozessersetzung unterstützt, würde ich Folgendes ausführen:Das macht so ziemlich das Gleiche wie die vorherigen
ed
Befehle.quelle
Der Perl Weg:
Viel einfacher zu lesen als
sed
, schneller, kein Risiko, unerwünschte Zeilen zu wählen.quelle
Wenn das nur für Grepping-Prozesse mit vollständigen Überschriften ist, würde ich @ mrbs Vorschlag erweitern:
pgrep bash | xargs ps -fp
wird das gleiche Ergebnis erhalten, aber ohne eine Unterschale. Wenn eine andere Formatierung erforderlich ist:quelle
Wenn Sie die genauen Zeilennummern kennen, ist das mit Perl ganz einfach! Wenn Sie die Zeilen 1 und 5 aus einer Datei erhalten möchten, sagen Sie / etc / passwd:
Wenn Sie auch andere Zeilen erhalten möchten, fügen Sie einfach deren Nummern in das Array ein.
quelle