grep eine Datei, aber mehrere umgebende Linien anzeigen?

3418

Ich möchte grepfür eine Zeichenfolge, aber auch die vorhergehenden fünf Zeilen und die folgenden fünf Zeilen sowie die übereinstimmende Zeile anzeigen. Wie könnte ich das tun?

Mark Harrison
quelle
3
Zu diesem Zweck habe ich eine Kopie von Brendan Greggs Perl-Skript in der Nähe . Funktioniert gut.
Ethan Post
6
Eine Lösung für Solaris finden Sie unter diesem Link .
Jahroy
106
man grep | grep -C 1 context:)
StvnW
20
man grep | grep -C 1 "\-C";)
Anders B
9
@StvnW ... Ich weiß nicht, ob ich dieses Meta aufrufen soll (in einem allgemeineren statt in einem SO-Kontext) oder wie ich es nennen soll. Sie haben die Frage beantwortet, indem Sie gezeigt haben, wie Sie die Antwort verwenden, um die Antwort zu finden.
bballdave025

Antworten:

4537

Für BSD oder GNU können grep Sie -B numfestlegen, wie viele Zeilen vor dem Spiel und wie viele -A numZeilen nach dem Spiel vorhanden sind.

grep -B 3 -A 2 foo README.txt

Wenn Sie die gleiche Anzahl von Zeilen vor und nach der Verwendung wünschen -C num.

grep -C 3 foo README.txt

Dies zeigt 3 Zeilen vor und 3 Zeilen nach.

Pat Notz
quelle
56
Es ist gut, aber leider unterstützt das Solaris grep das nicht. Siehe diesen Link für Solaris: unix.com/solaris/33533-grep-display-few-lines-before-after.html
рüффп
9
Ok, aber was ist, wenn alle Ausgabezeilen nach dem Match angezeigt werden sollen? grep -A0 und grep -A-1 schneiden es nicht ...
g33kz0r
2
funktioniert aus irgendeinem Grund nicht für mich, obwohl in meinen Manpages erwähnt.
Hayri Uğur Koltuk
2
Wenn Sie HP-UX env sind, funktioniert keine der grep-Versionen wie in Solaris. Konnte den Solaris-Link verwenden, aber nawk durch awk in diesem Link ersetzen.
Zkarthik
6
-n steht für Zeilennummern, aber für einige Versionen von grep zeigt -n # # umgebende Zeilen (wie -c) mit Zeilennummern an. Das ist eine nützliche Abkürzung, die ich brauche, wenn ich Kontext brauche.
Anthony DiSanti
607

-Aund -Bfunktioniert genauso wie -C n(für nKontextzeilen) oder nur -n(für nKontextzeilen ... solange n 1 bis 9 ist).

Stu
quelle
Ich habe das -nFormat ausprobiert und herausgefunden, dass es nur bis funktioniert 9. Denn 15es gibt 5 Zeilen zurück
Deepak Mahakale
7
@DeepakMahakale Dies hängt wahrscheinlich damit zusammen, wie Befehlszeilenargumente / -optionen normalerweise von POSIX-Programmen analysiert werden. Die Option Spezifizierer ein einzelnes Zeichen (wie zum Beispiel -A, -Boder -C). Normalerweise folgt auf den Optionsspezifizierer ein Wert ( -o a.outum die Ausgabedatei in GCC anzugeben), er kann jedoch auch als einfacher Schalter / Flag fungieren ( -gum Debugging-Informationen in GCC zu aktivieren). Leerzeichen zwischen Optionen sind jedoch optional. Bei Optionen ohne Wert können sie daher zusammengeführt werden ( -ABC). Dies bedeutet, dass sie -15interpretiert werden -1 -5(zwei separate Optionen) und die Optionen -5überschrieben -1.
Natiiix
1
-5 ist schneller als beide -A 5 -B 5. Diese dürfen nicht zusammen verwendet werden. Für andere Leser des Skripts ist es sauberer, wenn Sie -A oder -B oder -C über -9 wählen.
Eric Aldinger
76

ack arbeitet mit ähnlichen Argumenten wie grep und akzeptiert -C. Normalerweise ist es jedoch besser, Code zu durchsuchen.

Elmarco
quelle
5
ack unterstützt auch -A -B.
Shuo
Ack ist in vielerlei Hinsicht besser als grep. Es ist schneller mit einer einfacheren Syntax.
Chim
1
grep hat jedoch den Vorteil, dass es auf vielen Systemen standardmäßig installiert ist.
Marc Z
1
@MarcZ: Richtig, grep wird eher standardmäßig installiert als ack, aber ack ist ein portables, eigenständiges Skript. Sie müssen es nicht kompilieren oder in einem Systemverzeichnis wie / usr / bin / installieren. Sobald es heruntergeladen und in ein Verzeichnis gestellt wurde, das im $ PATH aufgeführt ist (und dessen eXecute-Berechtigungsbit gesetzt ist), sollte es sofort funktionieren. (Es sind keine Sudo- oder Root-Berechtigungen erforderlich, damit die Bestätigung funktioniert.)
JL
Bei dieser Frage geht es darum grep, nicht sicher zu sein, ob sie zum "Werben" verwendet wird ack(was in der Tat ein großartiges Werkzeug ist).
MonsieurDart
39
grep astring myfile -A 5 -B 5

Das wird "myfile" für "astring" greifen und 5 Zeilen vor und nach jedem Match anzeigen

dbr
quelle
19
"grep astring myfile -C 5" wird das gleiche tun
Syed Siraj Uddin
20

Ich benutze normalerweise

grep searchstring file -C n # n for number of lines of context up and down

Viele der Tools wie grep haben auch wirklich großartige Man-Dateien. Ich beziehe mich oft auf die Manpage von grep, weil man so viel damit anfangen kann.

man grep

Viele GNU-Tools verfügen auch über eine Infoseite, die neben der Manpage möglicherweise weitere nützliche Informationen enthält.

info grep
Sam Merrell
quelle
13

Verwenden Sie grep

$ grep --help | grep -i context
Context control:
  -B, --before-context=NUM  print NUM lines of leading context
  -A, --after-context=NUM   print NUM lines of trailing context
  -C, --context=NUM         print NUM lines of output context
  -NUM                      same as --context=NUM
Chiel ten Brinke
quelle
Haben Sie die akzeptierte Antwort nicht gelesen? Sie wiederholen nur, was bereits zu einer fast 10 Jahre alten Frage gesagt wurde ...
Yokai
7
Oh, tut mir leid, Yokai. Aber ich lese nichts über das Durchsuchen des Hilfeabschnitts von grep, um die Antwort abzurufen.
Chiel ten Brinke
1
@ Yokai Abgesehen von dem, was Chiel ten Brinke sagte, erwähnt die akzeptierte Antwort nicht die langen Optionen
user3738870
10

Suchen Sie in "/some/file.txt" nach "17655" und zeigen Sie den 10-Zeilen-Kontext vor und nach (mit Awk) an. Die Ausgabe wird mit der Zeilennummer gefolgt von einem Doppelpunkt versehen. Verwenden Sie diese Option unter Solaris, wenn 'grep' die Optionen "- [ACB]" nicht unterstützt.

awk '

/17655/ {
        for (i = (b + 1) % 10; i != b; i = (i + 1) % 10) {
                print before[i]
        }
        print (NR ":" ($0))
        a = 10
}

a-- > 0 {
        print (NR ":" ($0))
}

{
        before[b] = (NR ":" ($0))
        b = (b + 1) % 10
}' /some/file.txt;
Malcolm Boekhoff
quelle
7

ripgrep

Wenn Sie sich für die Leistung interessieren, verwenden Sie ripgrepeine ähnliche Syntax wie grepz

rg -C5 "pattern" .

-C, --context NUM- NUM-Zeilen vor und nach jedem Spiel anzeigen.

Es gibt auch Parameter wie -A/ --after-contextund -B/ --before-context.

Das Tool basiert auf der Regex-Engine von Rust, wodurch es bei großen Datenmengen sehr effizient ist .

Kenorb
quelle
5

Hier ist die @ Ygor-Lösung inawk

awk 'c-->0;$0~s{if(b)for(c=b+1;c>1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=3 a=3 s="pattern" myfile

Hinweis: Ersetzen aund bVariablen durch Anzahl der Zeilen davor und danach.

Es ist besonders nützlich für das System , das nicht grep unterstützt -A, -Bund -CParameter.

Kenorb
quelle
4
$ grep thestring thefile -5

-5bringt Sie 5Linien über und unter dem Match 'thestring' ist gleichbedeutend mit -C 5oder -A 5 -B 5.

JBone
quelle
4

Grep hat eine Option namens Context Line Control, Sie können die --contextdarin einfach verwenden

| grep -C 5

oder

| grep -5

Sollte den Trick machen

Prime
quelle
1

Ich mache den kompakten Weg

grep -5 string file

Das ist das Äquivalent von

grep -A 5 -B 5 string file
Franzisk
quelle
0

Wenn Sie häufig nach Code suchen, ist AG, der Silbersucher, viel effizienter (dh schneller) als grep.

Sie zeigen Kontextzeilen mit der Option -C an.

Z.B:

ag -C 3 "foo" myFile

line 1
line 2
line 3
line that has "foo"
line 5
line 6
line 7
Rose
quelle