С GNU grep:
N=10; grep -roP ".{0,$N}foo.{0,$N}" .
Объяснение:
-o => Печатайте только то, что вам подходит
-P => Используйте регулярные выражения в стиле Perl
- Регулярное выражение говорит, что соответствует 0
$Nсимволам, затем 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то grep, чтобы быть GNU , мы используем 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 То есть, предпочитайте не сопоставлять что-либо, если только это не приведет к сбою в общем совпадении. Короче говоря, подберите как можно меньше символов.