Muszę przeszukiwać niektóre pliki JSON, w których długość linii przekracza kilka tysięcy znaków. Jak mogę ograniczyć grep do wyświetlania kontekstu do N znaków po lewej i prawej stronie dopasowania? Każde narzędzie inne niż grep byłoby również w porządku, o ile jest dostępne w popularnych pakietach Linux.
Byłby to przykładowy wynik dla wyimaginowanego przełącznika grep Ф :
$ 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
Odpowiedzi:
Z GNU
grep
:Wyjaśnienie:
-o
=> Drukuj tylko to, co pasowałeś-P
=> Użyj wyrażeń regularnych w stylu Perla$N
znaków, afoo
następnie 0 do$N
znaków.Jeśli nie masz GNU
grep
:Wyjaśnienie:
Ponieważ nie możemy dłużej polegać na
grep
byciu GNUgrep
, używamyfind
do wyszukiwania plików rekurencyjnie (-r
działanie GNUgrep
). Dla każdego znalezionego pliku uruchamiamy fragment Perla.Przełączniki Perla:
-n
Czytaj plik linia po linii-l
Usuń nowy wiersz na końcu każdej linii i włóż go z powrotem podczas drukowania-e
Traktuj następujący ciąg jako kodFragment Perla robi w zasadzie to samo, co
grep
. Zaczyna się od ustawienia zmiennej$N
na liczbę znaków kontekstu, które chcesz. TeBEGIN{}
środki to jest wykonywane tylko raz na początku realizacji nie raz dla każdego wiersza w każdym pliku.Instrukcja wykonywana dla każdej linii ma wydrukować linię, jeśli zadziała podstawienie wyrażenia regularnego.
Wyrażenie regularne:
^.*?
), a następnie.{0,$N}
jak wgrep
przypadku, afoo
następnie kolejne.{0,$N}
i ostatecznie dopasuj dowolne stare rzeczy leniwie do końca wiersza (.*?$
).$ARGV:$1
.$ARGV
to magiczna zmienna przechowująca nazwę czytanego pliku.$1
jest to, co pasowały parens: kontekst w tym przypadku.foo
bez niepowodzenia dopasowania (ponieważ.{0,$N}
dozwolone jest dopasowanie zero razy).1 Oznacza to, że wolę nie dopasowywać niczego, chyba że spowodowałoby to niepowodzenie ogólnego dopasowania. Krótko mówiąc, dopasuj jak najmniej znaków.
źródło
| grep foo
do końca (jednak tracąc podświetlanie nazwy pliku w tym procesie).grep
możesz określić dopasowanie kolorów / aplikacji na podstawie flag zastosowanych za pomocą zmiennych środowiskowych. więc może nawet mógłbyś wygrać je wszystkie (bez obietnic - nawet nie jestem pewien, czy to zadziała w tym przypadku), ale osobiście nie widzę tu znaczenia ... w każdym razie ... graj dalej.zsh
nie jestem w stanie zmusić go do działania, przekazując N = 10 jak w przykładzie. Działa to jednak, jeśliexport N=10
uruchomię to polecenie. Masz pomysł, jak dostosować przykład do pracy z zsh?perl -lne 'print "$ARGV: $_" for /.{0,10}foo.{0,10}/g'
Spróbuj użyć tego:
-E mówi, że chcesz użyć rozszerzonego wyrażenia regularnego
-o mówi, że chcesz wydrukować tylko dopasowanie
-r grep szuka wyniku rekurencyjnie w folderze
REGEX:
{0,10} mówi, ile dowolnych znaków chcesz wydrukować
. reprezentuje dowolną postać (sama postać nie była tutaj ważna, tylko jej liczba)
Edycja: Rozumiem, że Joseph zaleca prawie takie samo rozwiązanie jak ja: D
źródło
-E
jest znacznie szybszy niż-P
.Zaczerpnięte z: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/ oraz https: // stackoverflow. com / a / 39029954/1150462
Sugerowane podejście
".{0,10}<original pattern>.{0,10}"
jest całkowicie dobre, z tym wyjątkiem, że kolor wyróżniający jest często pomieszany. Utworzyłem skrypt o podobnym wyniku, ale kolor jest również zachowany:Zakładając, że skrypt jest zapisany jako
grepl
,grepl pattern file_with_long_lines
powinien wyświetlać pasujące linie, ale z pasującym łańcuchem tylko 10 znaków.źródło
Rurociągi standardowe
cut
z-b
flagą; możesz poinstruować wyjście grep do bajtów od 1 do 400 na linię.źródło