С 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 То есть, предпочитайте не сопоставлять что-либо, если только это не приведет к сбою в общем совпадении. Короче говоря, подберите как можно меньше символов.