So schneiden Sie lange übereinstimmende Zeilen ab, die von grep oder ack zurückgegeben werden

88

Ich möchte ack oder grep für HTML-Dateien ausführen, die oft sehr lange Zeilen haben. Ich möchte keine sehr langen Zeilen sehen, die wiederholt umbrochen werden. Aber ich möchte nur den Teil einer langen Zeile sehen, der eine Zeichenfolge umgibt, die dem regulären Ausdruck entspricht. Wie kann ich dies mit einer beliebigen Kombination von Unix-Tools erreichen?

Dan
quelle
1
Was ist ack? Ist es ein Befehl, den Sie verwenden, wenn Sie etwas nicht mögen? So etwas wie ack file_with_long_lines | grep pattern? :-)
Alok Singhal
6
@Alok ack(bekannt als ack-grepDebian) ist grepauf Steroiden. Es hat auch die --thppptOption (kein Scherz). betterthangrep.com
ZoogieZork
Vielen Dank. Ich habe heute etwas gelernt.
Alok Singhal
Während die --thppptFunktion etwas umstritten ist, scheint der entscheidende Vorteil zu sein , dass Sie Perl verwenden können Regexes direkt, nicht ein paar verrückten [[:space:]]und Zeichen wie {, [etc. mit dem Bedeutungswandel -eund -Eschaltet in eine Weise , die zu erinnern , unmöglich ist.
Evgeni Sergeev

Antworten:

98

Sie können die Option grep verwenden -o, möglicherweise in Kombination mit dem Ändern Ihres Musters ".{0,10}<original pattern>.{0,10}"in, um einen Kontext zu sehen:

       -o, --nur passend
              Zeigen Sie nur den Teil einer übereinstimmenden Zeile an, der mit MUSTER übereinstimmt.

..oder -c:

       -c, --count
              Normale Ausgabe unterdrücken; Drucken Sie stattdessen eine Anzahl übereinstimmender Zeilen
              für jede Eingabedatei. Mit der Option -v, --invert-match (siehe
              unten), nicht übereinstimmende Zeilen zählen.
Äther
quelle
43
ein Beispiel: grep -oE ". {0,20} mysearchstring. {0,20}" myfile
Renaud
14
Sie sollten die Antwort ändern, um die Option -E hinzuzufügen, wie von @Renaud (erweiterte Musteroption) gezeigt, oder das vorgeschlagene Muster zum Erweitern des Kontexts funktioniert nicht.
Kriss
Vielleicht nicht nötig, aber hier ein Beispiel: $ echo "eeeeeeeeeeeeeeeeeeeeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrrrr" > fileonelongline.txt && grep -oE ".{0,20}MYSTRING.{0,20}" ./fileonelongline.txt DruckeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwww
Ulises Layera
43

Leiten Sie Ihre Ergebnisse durch cut. Ich denke auch darüber nach, einen --cutSchalter hinzuzufügen , damit man sagen --cut=80und nur 80 Spalten erhalten kann.

Andy Lester
quelle
8
Was ist, wenn der übereinstimmende Teil nicht aus den ersten 80 Zeichen besteht?
Ether
3
FWIW Ich habe an | cut=c1-120den Grep angehängt , für mich gearbeitet (obwohl ich nicht weiß, wie man passenden Text umschneidet )
Jake Rayson
25
| cut=c1-120hat nicht für mich funktioniert, ich musste tun| cut -c1-120
Ken Cochrane
1
Ich denke, @edib ist genau in der Syntax | cut -c 1-100 stackoverflow.com/a/48954102/1815624
CrandellWS
1
@AndyLester: Was ist mit einer --no-wrapOption, die verwendet $COLUMNS?
naught101
23

Sie könnten weniger als Pager verwenden, um lange Schlangen zu bestätigen und zu hacken: ack --pager="less -S" Dadurch wird die lange Zeile beibehalten, aber in einer Zeile belassen, anstatt sie zu umbrechen. Um mehr von der Linie zu sehen, scrollen Sie mit den Pfeiltasten weniger nach links / rechts.

Ich habe den folgenden Alias ​​eingerichtet, damit ack dies tun kann:

alias ick='ack -i --pager="less -R -S"' 
Jonah Braun
quelle
1
Bitte beachten Sie, dass Sie diesen --pagerBefehl in Ihre ~ / .ackrc-Datei einfügen können, wenn Sie ihn immer verwenden möchten.
Andy Lester
Das klingt bei weitem nach der besten Lösung für dieses Problem, das mich sehr nervt. Ich wünschte, ich wüsste, wie man es benutzt ack.
Brian Peterson
8
cut -c 1-100

erhält Zeichen von 1 bis 100.

edib
quelle
2

Entnommen aus: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/

Der vorgeschlagene Ansatz ".{0,10}<original pattern>.{0,10}"ist vollkommen gut, außer dass die Hervorhebungsfarbe oft durcheinander gebracht wird. Ich habe ein Skript mit einer ähnlichen Ausgabe erstellt, aber die Farbe bleibt auch erhalten:

#!/bin/bash

# Usage:
#   grepl PATTERN [FILE]

# how many characters around the searching keyword should be shown?
context_length=10

# What is the length of the control character for the color before and after the
# matching string?
# This is mostly determined by the environmental variable GREP_COLORS.
control_length_before=$(($(echo a | grep --color=always a | cut -d a -f '1' | wc -c)-1))
control_length_after=$(($(echo a | grep --color=always a | cut -d a -f '2' | wc -c)-1))

grep -E --color=always "$1" $2 |
grep --color=none -oE \
    ".{0,$(($control_length_before + $context_length))}$1.{0,$(($control_length_after + $context_length))}"

Angenommen, das Skript wird als gespeichert grepl, dann grepl pattern file_with_long_linessollten die übereinstimmenden Zeilen angezeigt werden, jedoch mit nur 10 Zeichen um die übereinstimmende Zeichenfolge.

xuhdev
quelle
Funktioniert, gibt aber für mich nachlaufenden Müll aus: ^ [[? 62; 9; c. Ich habe das Debuggen nicht versucht, weil mich die Antwort von @Jonah Braun zufriedenstellte.
sondra.kinsey
1

Folgendes mache ich:

function grep () {
  tput rmam;
  command grep "$@";
  tput smam;
}

In meinem .bash_profile überschreibe ich grep so, dass es automatisch tput rmamvorher und tput smamnachher ausgeführt wird, wodurch das Umbrechen deaktiviert und dann wieder aktiviert wird.

ognockocaten
quelle
Das ist eine schöne Alternative - außer wenn das eigentliche Spiel dann nicht auf dem Bildschirm angezeigt wird ...
Xerus
1

Geben Sie hier die Bildbeschreibung ein

In der ungewöhnlichen Situation, in der Sie nicht verwenden können -E, können Sie Folgendes verwenden:

grep -oe ".\{0,10\}error.\{0,10\}" mylogfile.txt
Josh Withee
quelle
0

Ich habe folgendes in mein .bashrc:

grepl() {
    $(which grep) --color=always $@ | less -RS
}

Sie können dann greplin der Befehlszeile alle Argumente verwenden, für die verfügbar ist grep. Verwenden Sie die Pfeiltasten, um das Ende längerer Zeilen anzuzeigen. Verwenden Sie qzu beenden.

Erläuterung:

  • grepl() {: Definieren Sie eine neue Funktion, die in jeder (neuen) Bash-Konsole verfügbar ist.
  • $(which grep): Holen Sie sich den vollständigen Weg von grep. (Ubuntu definiert einen Alias grep, der dem entspricht grep --color=auto. Wir wollen diesen Alias ​​nicht, sondern das Original grep.)
  • --color=always: Färben Sie die Ausgabe. ( --color=autoDer Alias ​​funktioniert nicht, da grepfestgestellt wird, dass die Ausgabe in eine Pipe eingefügt wird, und sie dann nicht eingefärbt wird.)
  • $@: Setzen Sie alle Argumente auf die grepl Funktion ein.
  • less: Zeigen Sie die Linien mit an less
  • -R: Farben anzeigen
  • S: Brechen Sie keine langen Schlangen
pt1
quelle