Зірвати персонажів до та після матчу?


144

Використовуючи це:

grep -A1 -B1 "test_pattern" file

створить один рядок до і після відповідного шаблону у файлі. Чи є спосіб відображення не рядків, а заданої кількості символів?

Рядок у моєму файлі досить великий, тому я не зацікавлений у друкуванні всього рядка, а лише спостерігаю за збігом у контексті. Будь-які пропозиції, як це зробити?


1
Дублікат unix.stackexchange.com/q/163726 Поруч дубліката stackoverflow.com/q/2034799
sondra.kinsey

Відповіді:


184

3 символи до і 4 символи після

$> echo "some123_string_and_another" | grep -o -P '.{0,3}string.{0,4}'
23_string_and

5
Хороша відповідь за невелику кількість даних, але вона починає повільно, коли ви співпадаєте> 100 символів - наприклад, у моєму гігантському XML-файлі, я хочу {1200 до і після, і це занадто повільно використовувати.
Benubird

3
Версія awk від @amit_g набагато швидша.
ssobczak

6
Недоступно на Mac OSX, тому насправді це не широко доступне рішення. Версія -E (перелічена нижче) є кращим рішенням. Що таке -P? Читайте далі ... -P, --perl-regexp Трактуйте PATTERN як регулярний вираз Perl (PCRE, див. Нижче). Це дуже експериментально, а греп -P може попередити про бездоганні функції.
Xofo

2
На OSX встановіть через: brew install homebrew/dupes/grepта запустіть його як ggrep.
kenorb

1
Як натякає @Benubird, це буде неможливо використовувати для величезних файлів із помірно широким оточенням, бажаним для цілі відповідності.
matanster

113
grep -E -o ".{0,5}test_pattern.{0,5}" test.txt 

Це відповідатиме до 5 символів до і після вашого шаблону. Перемикач -o повідомляє grep лише показувати відповідність, а -E використовувати розширений регулярний вираз. Не забудьте поставити лапки навколо свого виразу, інакше це може бути інтерпретоване оболонкою.


1
Хороший відповідь, цікаво , що він обмежений у 2 ^ 8-1 довжиною в {} так {0,255}роботах {0,256}даєgrep: invalid repetition count(s)
CodeMonkey

Здається, це стає значно менш ефективним, оскільки я збільшую кількість відповідних символів (5 -> 25 -> 50), будь-яка ідея чому?
Адам Хьюз

37

Ви можете використовувати

awk '/test_pattern/ {
    match($0, /test_pattern/); print substr($0, RSTART - 10, RLENGTH + 20);
}' file

2
Чудово працює навіть з дещо більшими файлами
Touko

4
як ви можете використовувати це для пошуку кількох збігів на рядок?
koox00

1
Яке значення першого числа у фігурних парних фігурах? Як і 0 у "grep -E -o". {0,5} test_pattern. {0,5} "test.txt"?
вентилятор Lew Rockwell

Це дійсно швидше, але не так точно, як відповідь @ ekse.
Абдолла

24

Ви маєте на увазі приблизно так:

grep -o '.\{0,20\}test_pattern.\{0,20\}' file

?

Це буде друкувати до двадцяти символів з обох боків від test_pattern. \{0,20\}Позначення як *, але вказує , від нуля до двадцяти повторень замість нуля або more.The -oкаже , щоб показати тільки сам матч, а не всієї лінії.


Ця команда для мене не працює:grep: Invalid content of \{\}
Олександр Правдин

0

З gawk, ви можете використовувати функцію відповідності:

    x="hey there how are you"
    echo "$x" |awk --re-interval '{match($0,/(.{4})how(.{4})/,a);print a[1],a[2]}'
    ere   are

Якщо з вами все гаразд perl, більш гнучке рішення: Далі буде надруковано три символи перед шаблоном, за яким слід фактичний малюнок, а потім 5 символів після шаблону.

echo hey there how are you |perl -lne 'print "$1$2$3" if /(.{3})(there)(.{5})/'
ey there how

Це також може бути застосоване до слів, а не лише до символів. Далі буде надруковано одне слово перед фактичним збігом рядків.

echo hey there how are you |perl -lne 'print $1 if /(\w+) there/'
hey

Далі буде надруковано одне слово за зразком:

echo hey there how are you |perl -lne 'print $2 if /(\w+) there (\w+)/'
how

Далі буде надруковано одне слово перед візерунком, потім власне слово, а потім одне слово після шаблону:

echo hey there how are you |perl -lne 'print "$1$2$3" if /(\w+)( there )(\w+)/'
hey there how

0

Ви можете використовувати regexp grep для знаходження + другий греп для виділення

echo "some123_string_and_another" | grep -o -P '.{0,3}string.{0,4}' | grep string

23_string_and

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


0

Я ніколи не легко запам’ятаю ці критичні модифікатори команд, тому я взяв верхню відповідь і перетворив її на функцію у моєму ~/.bashrcфайлі:


cgrep() {
    # For files that are arrays 10's of thousands of characters print.
    # Use cpgrep to print 30 characters before and after search patttern.
    if [ $# -eq 2 ] ; then
        # Format was 'cgrep "search string" /path/to/filename'
        grep -o -P ".{0,30}$1.{0,30}" "$2"
    else
        # Format was 'cat /path/to/filename | cgrep "search string"
        grep -o -P ".{0,30}$1.{0,30}"
    fi
} # cgrep()

Ось як це виглядає в дії:

$ ll /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

-rw-r--r-- 1 rick rick 25780 Jul  3 19:05 /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

$ cat /tmp/rick/scp.Mf7UdS/Mf7UdS.Source | cgrep "Link to iconic"

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

$ cgrep "Link to iconic" /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

Файл, про який йдеться, - це один безперервний рядок розміром 25 К, і ви не можете надіслати те, що шукаєте, використовуючи звичайний grep .

Зверніть увагу на два різні способи викликати метод cgrepпаралелей grep.

Існує "niftier" спосіб створення функції, коли "$ 2" передається лише тоді, коли встановлено, що дозволить зберегти 4 рядки коду. Я не маю це корисно, хоча. Щось подібне ${parm2} $parm2. Якщо я знайду, я перегляну функцію та цю відповідь.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.