Com o GNU grep
:
N=10; grep -roP ".{0,$N}foo.{0,$N}" .
Explicação:
-
-o
= > Imprimir apenas o que você combinou -
-P
= > Use expressões regulares no estilo Perl - A regex diz a correspondência 0 a
$N
caracteres seguidos porfoo
seguidos por 0 a$N
caracteres.
Se você não tiver o GNU grep
:
find . -type f -exec \
perl -nle '
BEGIN{$N=10}
print if s/^.*?(.{0,$N}foo.{0,$N}).*?$/$ARGV:$1/
' {} \;
Explicação:
Como não podemos mais depender de grep
sendo GNU grep
, usamos find
para procurar arquivos recursivamente (a ação -r
do GNU grep
). Para cada arquivo encontrado, executamos o snippet Perl.
Perl muda:
-
-n
Leia o arquivo linha por linha -
-l
Remova a nova linha no final de cada linha e coloque-a de volta ao imprimir -
-e
Tratar a seguinte string como código
O trecho de Perl está fazendo essencialmente a mesma coisa que grep
. Ele começa definindo uma variável $N
para o número de caracteres de contexto que você deseja. O BEGIN{}
significa que isso é executado apenas uma vez no início da execução, não uma vez para cada linha em cada arquivo.
A declaração executada para cada linha é para imprimir a linha se a substituição de expressão regular funcionar.
O regex:
- Corresponda qualquer coisa antiga preguiçosamente 1 no início da linha (
^.*?
) seguido por.{0,$N}
como no casogrep
, seguido porfoo
seguido por outro.{0,$N}
e finalmente combinar qualquer coisa antiga preguiçosamente até o final da linha (.*?$
). - Substituímos isso por
$ARGV:$1
.$ARGV
é uma variável mágica que contém o nome do arquivo atual que está sendo lido.$1
é o que os parênteses corresponderam: o contexto neste caso. - As correspondências lazy em cada extremidade são necessárias porque uma correspondência desejada comeria todos os caracteres antes de
foo
sem deixar de corresponder (pois.{0,$N}
tem permissão para corresponder zero vezes).
1 Ou seja, prefere não corresponder a nada, a menos que isso cause falha na correspondência geral. Resumidamente, combine o menor número de caracteres possível.