Com o GNU grep
:
N=10; grep -roP ".{0,$N}foo.{0,$N}" .
Explicação:
-o
=> Imprima apenas o que você combinou
-P
=> Use expressões regulares no estilo Perl
- O regex diz corresponder 0 aos
$N
caracteres foo
seguido por 0 aos $N
caracteres.
Se você não possui 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 confiar em grep
ser o GNU grep
, utilizamos find
para procurar arquivos recursivamente (a -r
ação do GNU grep
). Para cada arquivo encontrado, executamos o snippet Perl.
Comutadores Perl:
-n
Leia o arquivo linha por linha
-l
Remova a nova linha no final de cada linha e coloque-a novamente ao imprimir
-e
Trate a seguinte string como código
O snippet Perl está fazendo essencialmente a mesma coisa que grep
. Começa definindo uma variável $N
para o número de caracteres de contexto que você deseja. Os BEGIN{}
meios que isso é executado apenas uma vez no início da execução, não uma vez para cada linha em cada arquivo.
A instrução executada para cada linha é imprimir a linha se a substituição de regex funcionar.
A regex:
- Faça a correspondência de qualquer coisa antiga preguiçosamente 1 no início da linha (
^.*?
) seguida por, .{0,$N}
como no grep
caso, foo
seguido de outra .{0,$N}
e, finalmente, faça a correspondência de qualquer coisa antiga preguiçosamente até o final da linha ( .*?$
).
- Nós 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 combinavam: o contexto neste caso.
- As correspondências preguiçosas em cada extremidade são necessárias porque uma correspondência gananciosa consumiria todos os caracteres antes
foo
sem deixar de corresponder (já que .{0,$N}
é permitido corresponder zero vezes).
1 Ou seja, prefira não corresponder a nada, a menos que isso cause uma falha na correspondência geral. Em resumo, combine o mínimo de caracteres possível.