Con GNU grep
:
N=10; grep -roP ".{0,$N}foo.{0,$N}" .
Explicación:
-o
=> Imprime solo lo que hiciste coincidir
-P
=> Usar expresiones regulares de estilo Perl
- La expresión regular dice que coincida con 0 a los
$N
caracteres foo
seguido de 0 seguido por los $N
caracteres.
Si no tienes GNU grep
:
find . -type f -exec \
perl -nle '
BEGIN{$N=10}
print if s/^.*?(.{0,$N}foo.{0,$N}).*?$/$ARGV:$1/
' {} \;
Explicación:
Como ya no podemos confiar en grep
ser GNU grep
, utilizamos find
para buscar archivos de forma recursiva (la -r
acción de GNU grep
). Para cada archivo encontrado, ejecutamos el fragmento de Perl.
Interruptores Perl:
-n
Lee el archivo línea por línea
-l
Elimine la nueva línea al final de cada línea y vuelva a colocarla al imprimir
-e
Trate la siguiente cadena como código
El fragmento de Perl está haciendo esencialmente lo mismo que grep
. Comienza configurando una variable $N
al número de caracteres de contexto que desea. Esto BEGIN{}
significa que esto se ejecuta solo una vez al comienzo de la ejecución, no una vez por cada línea en cada archivo.
La instrucción ejecutada para cada línea es imprimir la línea si la sustitución de expresiones regulares funciona.
La expresión regular:
- Haga coincidir cualquier cosa antigua perezosamente 1 al comienzo de la línea (
^.*?
) seguido de .{0,$N}
como en el grep
caso, foo
seguido de otro seguido .{0,$N}
y finalmente haga coincidir cualquier cosa vieja perezosamente hasta el final de la línea ( .*?$
).
- Sustituimos esto con
$ARGV:$1
. $ARGV
es una variable mágica que contiene el nombre del archivo actual que se está leyendo. $1
es lo que emparejaron los padres: el contexto en este caso.
- Las coincidencias perezosas en cualquier extremo son necesarias porque una coincidencia codiciosa se comería a todos los personajes antes
foo
sin fallar (ya que .{0,$N}
se permite que coincidan cero veces).
1 Es decir, prefiera no hacer coincidir nada a menos que esto haga que falle la coincidencia general. En resumen, combine la menor cantidad de caracteres posible.