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
$Ncaracteres fooseguido de 0 seguido por los $Ncaracteres.
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 grepser GNU grep, utilizamos findpara buscar archivos de forma recursiva (la -racció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 $Nal 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 grepcaso, fooseguido 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. $ARGVes una variable mágica que contiene el nombre del archivo actual que se está leyendo. $1es 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
foosin 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.