Как обрезать длинные совпадающие строки, возвращаемые grep или ack


90

Я хочу запустить ack или grep для файлов HTML, которые часто содержат очень длинные строки. Я не хочу видеть очень длинные строки, которые повторяются постоянно. Но я действительно хочу видеть только ту часть длинной строки, которая окружает строку, соответствующую регулярному выражению. Как я могу получить это, используя любую комбинацию инструментов Unix?


1
Что ack? Вы используете эту команду, когда вам что-то не нравится? Что-то вроде ack file_with_long_lines | grep pattern? :-)
Алок Сингхал

6
@Alok ack(известный как ack-grepDebian) принимает grepстероиды. Тоже есть --thppptопция (не шучу). betterthangrep.com
ZoogieZork

Спасибо. Я кое-что узнал сегодня.
Алок Сингхал,

1
В то время как --thppptфункция несколько спорна, главное преимущество , кажется, что вы можете использовать Perl регулярных выражений непосредственно, а не какие - то сумасшедшее [[:space:]]и символы , такие как {, [и т.д. изменяя смысл с -eи -Eпереключается таким образом , что это невозможно запомнить.
Евгений Сергеев

Ответы:


99

Вы можете использовать опцию grep -o, возможно, в сочетании с изменением вашего шаблона на ".{0,10}<original pattern>.{0,10}", чтобы увидеть некоторый контекст вокруг него:

       -o, --only-matching
              Показать только ту часть совпадающей строки, которая соответствует ШАБЛОНУ.

..или -c:

       -c, --count
              Подавить нормальный вывод; вместо этого напечатайте количество совпадающих строк
              для каждого входного файла. С опцией -v, --invert-match (см.
              ниже), подсчитайте несовпадающие строки.

44
пример: grep -oE ". {0,20} mysearchstring. {0,20}" myfile
Renaud

14
вам следует изменить ответ на добавление опции -E, как показано @Renaud (опция расширенного шаблона), или предложенный шаблон для расширения контекста не будет работать.
Крисс

Возможно, это не так необходимо, но вот пример: $ echo "eeeeeeeeeeeeeeeeeeeeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrrrr" > fileonelongline.txt && grep -oE ".{0,20}MYSTRING.{0,20}" ./fileonelongline.txt распечаткиqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwww
Ulises Layera

Это хорошо работает; но заметным недостатком является то, что при использовании, например, oE ".{0,20}mysearchstring.{0,20}"вы теряете выделение внутренней «исходной» строки по отношению к контексту, потому что все это становится шаблоном поиска. Хотел бы найти способ сохранить некоторый невыделенный контекст вокруг результатов поиска для гораздо более легкого визуального сканирования и интерпретации результатов.
Аарон Валлентин,

1
О, вот решение проблемы с подсветкой, вызванной использованием -oE ".{0,x}foo.{0,x}"подхода (где x- количество символов контекста) - добавить `| grep foo `до конца. Работает как с решениями ack, так и с grep. Другие решения также здесь: unix.stackexchange.com/questions/163726/…
Аарон Валлентин,

44

Сообщите о своих результатах cut. Я также подумываю добавить --cutпереключатель, чтобы вы могли сказать --cut=80и получить только 80 столбцов.


8
Что делать, если совпадающая часть не входит в первые 80 символов?
Ether

3
FWIW, который я добавил | cut=c1-120к grep, сработал для меня (хотя не знаю, как обрезать совпадающий текст)
Джейк Рэйсон

26
| cut=c1-120не сработало для меня, мне нужно было сделать| cut -c1-120
Кен Кокрейн

1
Я думаю, что @edib точен в синтаксисе | cut -c 1-100 stackoverflow.com/a/48954102/1815624
CrandellWS

1
@AndyLester: А как насчет --no-wrapопции, которая использует $COLUMNS?
naught101 08

25

Вы можете использовать less в качестве пейджера для подтверждения и вырезания длинных строк: ack --pager="less -S" это сохраняет длинную строку, но оставляет ее на одной строке вместо переноса. Чтобы увидеть большую часть строки, прокрутите влево / вправо меньше с помощью клавиш со стрелками.

Для этого у меня есть следующий псевдоним:

alias ick='ack -i --pager="less -R -S"' 

2
Обратите внимание, что вы можете поместить эту --pagerкоманду в свой файл ~ / .ackrc, если хотите всегда использовать ее.
Энди Лестер

Это звучит как лучшее решение этой проблемы, которая меня очень беспокоит. Хотел бы я знать, как пользоваться ack.
Брайан Петерсон

@BrianPeterson ackпочти такой же grep, только проще в самых распространенных случаях
Аарон Валлентин


2

Взято из: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preservations-color/

Предлагаемый подход ".{0,10}<original pattern>.{0,10}"идеален, за исключением того, что цвет подсветки часто путается. Я создал сценарий с аналогичным выводом, но цвет также сохранился:

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

Предполагая, что сценарий сохранен как grepl, тогда grepl pattern file_with_long_linesдолжны отображаться совпадающие строки, но только с 10 символами вокруг соответствующей строки.


Работает, но выводит конечный мусор, например: ^ [[? 62; 9; c. Я не пробовал отладку, потому что ответ @Jonah Braun меня удовлетворил.
sondra.kinsey

1

Вот что я делаю:

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

В моем .bash_profile я переопределяю grep, чтобы он автоматически запускался tput rmamдо и tput smamпосле, что отключило перенос, а затем снова включило его.


Это хорошая альтернатива - если только фактическое совпадение не отображается ...
Ксерус,

1

введите описание изображения здесь

В необычной ситуации, когда вы не можете использовать -E, вы можете использовать:

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

0

Я вложил в свой .bashrc:

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

Затем вы можете использовать greplв командной строке любые аргументы, доступные для grep. Используйте клавиши со стрелками, чтобы увидеть хвост более длинных линий. Используйте qдля выхода.

Пояснение:

  • grepl() {: Определите новую функцию, которая будет доступна в каждой (новой) консоли bash.
  • $(which grep): Получить полный путь grep. (Ubuntu определяет псевдоним grep, эквивалентный grep --color=auto. Нам нужен не этот псевдоним, а оригинал grep.)
  • --color=always: Раскрасить вывод. ( --color=autoиз псевдонима не будет работать, так как grepобнаруживает, что вывод помещен в канал, и не будет его раскрашивать.)
  • $@: Поместите greplсюда все аргументы, данные функции.
  • less: Отобразить строки с помощью less
  • -R: Показать цвета
  • S: Не разрывайте длинные строки
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.