Ich muss einige JSON-Dateien durchgehen, in denen die Zeilenlängen einige tausend Zeichen überschreiten. Wie kann ich grep einschränken, um den Kontext bis zu N Zeichen links und rechts von der Übereinstimmung anzuzeigen? Jedes andere Tool als grep wäre ebenfalls in Ordnung, solange es in gängigen Linux-Paketen verfügbar ist.
Dies wäre eine Beispielausgabe für den imaginären grep-Schalter Ф :
$ grep -r foo *
hello.txt: Once upon a time a big foo came out of the woods.
$ grep -Ф 10 -r foo *
hello.txt: ime a big foo came of t
Antworten:
Mit GNU
grep
:Erläuterung:
-o
=> Nur das drucken, was du gefunden hast-P
=> Verwenden Sie reguläre Ausdrücke im Perl-Stil$N
Zeichenfoo
mit 0 gefolgt von$N
Zeichen mit 0 übereinstimmen .Wenn Sie kein GNU haben
grep
:Erläuterung:
Da wir uns nicht mehr darauf verlassen können
grep
, GNU zu seingrep
,find
suchen wir rekursiv nach Dateien (die-r
Aktion von GNUgrep
). Für jede gefundene Datei führen wir das Perl-Snippet aus.Perl-Schalter:
-n
Lesen Sie die Datei Zeile für Zeile-l
Entfernen Sie den Zeilenumbruch am Ende jeder Zeile und setzen Sie ihn beim Drucken wieder ein-e
Behandeln Sie die folgende Zeichenfolge als CodeDas Perl-Snippet macht im Wesentlichen dasselbe wie
grep
. Zunächst wird eine Variable$N
auf die Anzahl der gewünschten Kontextzeichen gesetzt. DieBEGIN{}
Mittel , dies wird nur einmal zu Beginn der Ausführung nicht einmal für jede Zeile in jeder Datei ausgeführt.Die Anweisung, die für jede Zeile ausgeführt wird, gibt die Zeile aus, wenn die Regex-Ersetzung funktioniert.
Der Regex:
^.*?
) zu, gefolgt von.{0,$N}
wie imgrep
Fall,foo
gefolgt von einem anderen.{0,$N}
und ordnen Sie schließlich ein beliebiges altes Ding faul bis zum Ende der Zeile (.*?$
) zu.$ARGV:$1
.$ARGV
ist eine magische Variable, die den Namen der aktuell gelesenen Datei enthält.$1
Dazu passten die Eltern: der Kontext in diesem Fall.foo
ohne dass eine Übereinstimmung fehlschlägt (da.{0,$N}
null Übereinstimmungen zulässig sind).1 Das heißt, passen Sie lieber nichts an, es sei denn, dies würde dazu führen, dass die Gesamtübereinstimmung fehlschlägt. Kurz gesagt, stimmen Sie mit so wenigen Zeichen wie möglich überein.
quelle
| grep foo
am Ende umgangen werden kann (wobei jedoch die Hervorhebung des Dateinamens verloren geht).grep
Sie Match-Farben / -Anwendungen basierend auf Flags festlegen, die über Umgebungsvariablen angewendet werden. vielleicht so auch Sie können sie alle gewinnen (keine Versprechungen - nicht einmal sicher , wäre es in diesem Fall arbeiten) , aber ich habe nicht persönlich die Bedeutung hier sehen ... wie auch immer ... weiter spielen.zsh
ich nicht erreichen, dass es funktioniert, wenn N = 10 wie im Beispiel übergeben wird. Es funktioniert jedoch, wenn ichexport N=10
vor dem Ausführen des Befehls. Irgendeine Idee, wie man das Beispiel an die Arbeit mit zsh anpasst?perl -lne 'print "$ARGV: $_" for /.{0,10}foo.{0,10}/g'
Versuchen Sie diesen zu benutzen:
-E sagt, dass Sie erweiterte reguläre Ausdrücke verwenden möchten
-o sagt, dass Sie nur die Übereinstimmung drucken möchten
-r grep sucht rekursiv nach dem Ergebnis im Ordner
REGEX:
{0,10} gibt an , wie viele beliebige Zeichen gedruckt werden sollen
. stellt ein beliebiges Zeichen dar (ein Zeichen selbst war hier nicht wichtig, nur ihre Nummer)
Edit: Oh, ich sehe, dass Joseph fast die gleiche Lösung wie ich empfiehlt: D
quelle
-E
ist das deutlich schneller als-P
.Entnommen aus: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/ und https: // stackoverflow. com / a / 39029954/1150462
Der vorgeschlagene Ansatz
".{0,10}<original pattern>.{0,10}"
ist vollkommen gut, mit der Ausnahme, dass die Hervorhebungsfarbe oft durcheinander gebracht wird. Ich habe ein Skript mit einer ähnlichen Ausgabe erstellt, aber die Farbe bleibt auch erhalten:Angenommen, das Skript wird gespeichert als
grepl
, danngrepl pattern file_with_long_lines
sollten die übereinstimmenden Zeilen mit nur 10 Zeichen um die übereinstimmende Zeichenfolge angezeigt werden.quelle
Leiten von stdout zu
cut
mit der-b
Flagge; Sie können die Ausgabe von grep auf die Bytes 1 bis 400 pro Zeile beschränken.quelle