З GNU grep
:
N=10; grep -roP ".{0,$N}foo.{0,$N}" .
Пояснення:
-o
=> Роздрукуйте лише те, що ви відповідали
-P
=> Використовуйте регулярні вирази у стилі Perl
- У регулярному вираженні
$N
йде відповідність символів 0, а foo
потім 0 $N
символів.
Якщо у вас немає GNU grep
:
find . -type f -exec \
perl -nle '
BEGIN{$N=10}
print if s/^.*?(.{0,$N}foo.{0,$N}).*?$/$ARGV:$1/
' {} \;
Пояснення:
Оскільки ми більше не можемо покладатися на grep
GNU grep
, ми використовуємо find
для пошуку файлів рекурсивно ( -r
дія GNU grep
). Для кожного знайденого файлу ми виконуємо фрагмент Perl.
Перемикачі Perl:
-n
Прочитайте файл за рядком
-l
Видаліть новий рядок в кінці кожного рядка і поставте його назад під час друку
-e
Розгляньте наступний рядок як код
Фрагмент Perl робить по суті те саме, що і grep
. Він починається з встановлення змінної $N
на кількість потрібних символів контексту. Засіб BEGIN{}
це виконується лише один раз на початку виконання не один раз для кожного рядка кожного файлу.
Оператор, виконаний для кожного рядка, - це надрукувати рядок, якщо заміна регулярного вираження працює.
Регекс:
- Ліниво поєднуйте будь-яку стару річ 1 на початку,
^.*?
а потім, .{0,$N}
як у grep
випадку, за нею foo
слідує інша .{0,$N}
і, нарешті, ліниво до кінця рядка ( .*?$
).
- Ми замінюємо це на
$ARGV:$1
. $ARGV
- це магічна змінна, яка містить ім'я поточного файла, який читається. $1
це те, що відповідає паренам: контекст у даному випадку.
- Ліниві сірники в будь-якому кінці потрібні, тому що жадібний матч з'їдав би всіх персонажів раніше,
foo
не збігаючись (оскільки .{0,$N}
дозволено збігатися в нуль разів).
1 Тобто, волійте нічого не порівнювати, якщо це не спричинить збій загальної відповідності. Коротше кажучи, підберіть якомога менше символів.