Як усікати довгі відповідні рядки, що повертаються grep або ack


89

Я хочу запустити ack або grep на файлах HTML, які часто мають дуже довгі рядки. Я не хочу бачити дуже довгі рядки, які неодноразово загортаються. Але я хочу побачити лише ту частину довгого рядка, яка оточує рядок, що відповідає регулярному виразу. Як я можу отримати це за допомогою будь-якої комбінації інструментів Unix?


1
Що ack? Це команда, яку ви використовуєте, коли щось вам не подобається? Щось на зразок ack file_with_long_lines | grep pattern? :-)
Alok Singhal

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, --тільки-відповідність
              Показати лише ту частину відповідного рядка, яка відповідає ВЗОРУ.

..або -c:

       -c, --count
              Придушити нормальний вихід; замість цього надрукуйте кількість відповідних рядків
              для кожного вхідного файлу. З опцією -v, --invert-match (див
              нижче), підрахуйте невідповідні рядки.

44
приклад: grep -oE ". {0,20} mysearchstring. {0,20}" myfile
Рено

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

Можливо, це не потрібно, але ось приклад: $ echo "eeeeeeeeeeeeeeeeeeeeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrrrr" > fileonelongline.txt && grep -oE ".{0,20}MYSTRING.{0,20}" ./fileonelongline.txt принтиqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwww
Улісес Лаєра

Це добре працює; але примітним недоліком є ​​те, що, використовуючи, наприклад, oE ".{0,20}mysearchstring.{0,20}"ви втрачаєте виділення внутрішнього "оригінального" рядка проти контексту, оскільки все це стає шаблоном пошуку. Хотілося б знайти спосіб зберегти якийсь невиділений контекст навколо результатів пошуку для набагато легшого візуального сканування та інтерпретації результатів.
Аарон Валлентин,

1
О, ось вирішення проблеми висвітлення, спричиненої використанням -oE ".{0,x}foo.{0,x}"підходу (де xкількість символів контексту) - append `| grep foo `до кінця. Працює як для рішень ack, так і для grep. Більше рішень також тут: unix.stackexchange.com/questions/163726/…
Аарон Валлентин,

44

Проведіть свої результати до кінця cut. Я також розглядаю можливість додати --cutперемикач, щоб ви могли сказати --cut=80і отримати лише 80 стовпців.


8
Що робити, якщо частина, яка збігається, не містить перших 80 символів?
Ефір

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

25

Ви можете використовувати менше як пейджер для ack і рубати довгі рядки: ack --pager="less -S" це зберігає довгу лінію, але залишає її на одній лінії замість обгортання. Щоб побачити більше рядка, прокрутіть ліворуч / праворуч менше за допомогою клавіш зі стрілками.

У мене є така настройка псевдоніма для ack:

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

2
Зверніть увагу, що ви можете помістити цю --pagerкоманду у свій файл ~ / .ackrc, якщо ви завжди хочете її використовувати.
Енді Лестер

Це звучить як найкраще рішення цієї проблеми, яка мене дуже турбує. Я би хотів, щоб я знав, як користуватися ack.
Брайан Пітерсон

@BrianPeterson ackє майже таким же, як grepі лише простішим у найпоширеніших випадках
Aaron Wallentine


2

Взято з: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserva-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.