Jak obciąć długie pasujące wiersze zwracane przez grep lub ACK

90

Chcę uruchomić ACK lub Grep na plikach HTML, które często mają bardzo długie wiersze. Nie chcę widzieć wielokrotnie zawijanych bardzo długich linii. Ale chcę zobaczyć tylko tę część długiej linii, która otacza ciąg pasujący do wyrażenia regularnego. Jak mogę to uzyskać używając dowolnej kombinacji narzędzi Unix?

dan
źródło
1
Co ack? Czy jest to polecenie, którego używasz, gdy coś ci się nie podoba? Coś jak ack file_with_long_lines | grep pattern? :-)
Alok Singhal
6
@Alok ack(znany jako ack-grepDebian) jest grepna sterydach. Ma również --thppptopcję (nie żartuję). betterthangrep.com
ZoogieZork
Dzięki. Nauczyłem się czegoś dzisiaj.
Alok Singhal,
1
Podczas gdy --thppptfunkcja jest nieco kontrowersyjny, kluczem zaletą wydaje się, że można użyć Perl regexes bezpośrednio, a nie jakiś szalony [[:space:]]i znaków podoba {, [itp zmieniając sens z -ei -Eprzełącza się w taki sposób, że niemożliwe do zapamiętania.
Evgeni Sergeev,

Odpowiedzi:

99

Możesz użyć opcji grep -o, prawdopodobnie w połączeniu ze zmianą wzorca na ".{0,10}<original pattern>.{0,10}", aby zobaczyć otaczający go kontekst:

       -o, --only-matching
              Pokaż tylko część pasującej linii, która pasuje do PATTERN.

.. lub -c:

       -c, --count
              Tłumi normalne wyjście; zamiast tego wypisuje liczbę pasujących wierszy
              dla każdego pliku wejściowego. Z opcją -v, --invert-match (zobacz
              poniżej), policz niepasujące wiersze.
Eter
źródło
44
przykład: grep -oE ". {0,20} mysearchstring. {0,20}" myfile
Renaud
14
powinieneś zmienić odpowiedź, aby dodać opcję -E, jak pokazano przez @Renaud (opcja rozszerzonego wzorca), lub proponowany wzorzec rozszerzania kontekstu nie zadziała.
kriss
Może nie jest to konieczne, ale oto przykład: $ echo "eeeeeeeeeeeeeeeeeeeeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrrrr" > fileonelongline.txt && grep -oE ".{0,20}MYSTRING.{0,20}" ./fileonelongline.txt wydrukiqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwww
Ulises Layera
To działa dobrze; ale godną uwagi wadą jest to, że używając np., oE ".{0,20}mysearchstring.{0,20}"tracisz podświetlenie wewnętrznego „oryginalnego” ciągu w kontekście kontekstu, ponieważ całość staje się wzorcem wyszukiwania. Chciałbym znaleźć sposób na zachowanie nieokreślonego kontekstu wokół wyników wyszukiwania, aby znacznie ułatwić wizualne skanowanie i interpretację wyników.
Aaron Wallentine
1
Och, oto rozwiązanie problemu z podświetlaniem spowodowanego użyciem -oE ".{0,x}foo.{0,x}"podejścia (gdzie xjest liczba znaków kontekstu) - dodaj `| grep foo `do końca. Działa dla rozwiązań ACK lub GREP. Więcej rozwiązań również tutaj: unix.stackexchange.com/questions/163726/…
Aaron Wallentine
44

Przepuść swoje wyniki cut. Rozważam również dodanie --cutprzełącznika, abyś mógł powiedzieć --cut=80i uzyskać tylko 80 kolumn.

Andy Lester
źródło
8
Co się stanie, jeśli pasująca część nie znajduje się w pierwszych 80 znakach?
Ether
3
FWIW Dodałem | cut=c1-120do grepa , działało dla mnie (chociaż nie wiem, jak wyciąć dopasowany tekst)
Jake Rayson,
26
| cut=c1-120nie działało dla mnie, musiałem to zrobić| cut -c1-120
Ken Cochrane
1
Myślę, że @edib jest dokładny w składni | cut -c 1-100 stackoverflow.com/a/48954102/1815624
CrandellWS
1
@AndyLester: A co z --no-wrapopcją, która używa $COLUMNS?
naught101
25

Możesz użyć mniej jako pagera do potwierdzania i przycinania długich linii: ack --pager="less -S" To zachowuje długą linię, ale pozostawia ją w jednej linii zamiast zawijania. Aby zobaczyć więcej linii, przewijaj w lewo / w prawo mniej za pomocą klawiszy strzałek.

Mam następujący alias dla potwierdzenia, aby to zrobić:

alias ick='ack -i --pager="less -R -S"' 
Jonah Braun
źródło
2
Pamiętaj, że możesz umieścić to --pagerpolecenie w swoim pliku ~ / .ackrc, jeśli zawsze chcesz go używać.
Andy Lester,
To brzmi jak zdecydowanie najlepsze rozwiązanie tego problemu, który bardzo mnie wkurza. Chciałbym wiedzieć, jak używać ack.
Brian Peterson
@BrianPeterson ackjest prawie taki sam grep, tylko prostszy w najczęstszych przypadkach
Aaron Wallentine
8
cut -c 1-100

pobiera znaki od 1 do 100.

edib
źródło
2

Zaczerpnięte z: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/

Sugerowane podejście ".{0,10}<original pattern>.{0,10}"jest całkiem dobre, poza tym, że kolor podświetlenia jest często pomieszany. Stworzyłem skrypt z podobnym wynikiem, ale kolor też jest zachowany:

#!/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))}"

Zakładając, że skrypt jest zapisany jako grepl, grepl pattern file_with_long_linespowinien wyświetlić pasujące wiersze, ale tylko z 10 znakami wokół pasującego ciągu.

xuhdev
źródło
Działa, ale generuje dla mnie końcowe śmieci, na przykład: ^ [[? 62; 9; c. Nie próbowałem debugować, ponieważ odpowiedź @Jonah Braun mnie zadowoliła.
sondra.kinsey
1

Oto co robię:

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

W moim .bash_profile nadpisuję grep, tak aby był automatycznie uruchamiany tput rmamprzed i tput smampo, co wyłączyło zawijanie, a następnie ponownie go włączyło.

ognockocaten
źródło
To fajna alternatywa - chyba że mecz wypadnie poza ekran ...
Xerus
1

wprowadź opis obrazu tutaj

W nietypowej sytuacji, w której nie możesz użyć -E, możesz użyć:

grep -oe ".\{0,10\}error.\{0,10\}" mylogfile.txt
Josh Withee
źródło
0

Do mojego .bashrc:

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

Możesz następnie użyć greplw wierszu poleceń z dowolnymi argumentami, które są dostępne dla grep. Użyj klawiszy strzałek, aby zobaczyć koniec dłuższych linii. Użyj, qaby zakończyć.

Wyjaśnienie:

  • grepl() {: Zdefiniuj nową funkcję, która będzie dostępna w każdej (nowej) konsoli bash.
  • $(which grep): Uzyskaj pełną ścieżkę grep. (Ubuntu definiuje alias dla greptego jest równoważny z grep --color=auto. Nie chcemy tego aliasu, ale oryginał grep).
  • --color=always: Kolorowanie wydruku. ( --color=autoz aliasu nie zadziała, ponieważ grepwykrywa, że ​​wyjście jest umieszczone w potoku i nie będzie go wtedy kolorować).
  • $@: Umieść tutaj wszystkie argumenty przekazane greplfunkcji.
  • less: Wyświetl linie za pomocą less
  • -R: Pokaż kolory
  • S: Nie przerywaj długich linii
pt1
źródło