Estoy usando egrep ( grep -E
) con un archivo PATTERN. ( -f path/to/file
)
Esto se realiza en un bucle infinito en una secuencia de texto. Esto implica que no puedo acumular y pasar TODA la entrada a grep a la vez (como *.log
).
¿Hay alguna manera de hacer que grep "guarde" el NFA que está construyendo desde el archivo PATTERN para usarlo en su próxima ejecución?
He buscado en Google y he leído la documentación sin suerte.
Trataré de explicarlo un poco más. Necesito localizar un número fijo de cadenas con expresiones regulares (esto no es parte de una pregunta, pero siéntase libre de sugerir lo contrario) como direcciones IP, dominios, etc. La búsqueda se realiza en un feed de Internet. Puedes pensarlo como una secuencia de texto. No puedo usar grep
todas las entradas ya que es una secuencia. Puedo acumular un fragmento de flujo y usarlo grep
(por lo tanto, no usarlo grep
en cada línea), pero esto también es limitado (digamos durante 30 segundos).
Sé que grep
está construyendo un NFA a partir de todos sus patrones (en mi caso a partir de un archivo). Entonces mi pregunta aquí es: ¿puedo decirle grep
que guarde esa NFA para la próxima ejecución, ya que no va a cambiar? Eso me ahorraría el tiempo de construir esa NFA cada vez.
grep
por línea de texto? ¿De dónde viene el texto? ¿tail -f
Sería una opción?grep
esa parte.grep
varias veces. Posiblemente relacionado: ¿Por qué es tan lento hacer coincidir 1250 cadenas con patrones de 90k?grep
está destinado a funcionar en una secuencia de texto, todavía no entiendo por qué necesitarías ejecutar varias instancias. ¿Por qué no puedes alimentar a todos a la mismagrep
instancia? ¿Por qué necesitas acumularlos antes de alimentarlosgrep
?Respuestas:
No, no hay tal cosa. En general, el costo de iniciar
grep
(bifurcar un nuevo proceso, cargar el ejecutable, la biblioteca compartida, la vinculación dinámica ...) sería mucho mayor que compilar las expresiones regulares, por lo que este tipo de optimización tendría poco sentido.Sin embargo, vea ¿Por qué la coincidencia de 1250 cadenas con patrones de 90k es tan lenta? sobre un error en algunas versiones de GNU
grep
que lo haría particularmente lento para una gran cantidad de expresiones regulares.Posiblemente aquí, podría evitar correr
grep
varias veces alimentando sus fragmentos a la mismagrep
instancia, por ejemplo, usándolo como un coproceso y use un marcador para detectar el final. Conzsh
y GNUgrep
eawk
implementaciones que no seanmawk
:Aunque puede ser más simple hacer todo con
awk
o en superl
lugar.Pero si no necesita la
grep
salida para ir a diferentes archivos para diferentes fragmentos, siempre puede hacer:fuente
grep
tal como está. Gracias.¿Eres consciente de que las tuberías se bloquean? Si conecta algo a grep y toda la entrada no está disponible, grep esperará hasta que esté disponible y luego continuará como si la entrada estuviera allí todo el tiempo.
EDITAR: cómo funcionan las canalizaciones, por ejemplo,
cmd1 | cmd2
es que ambos programas se iniciarán al mismo tiempo, por ejemplo, con un "búfer de fragmentos" de 65.536 bytes entre ellos. Cuandocmd2
intenta leer y ese búfer está vacío, esperará a que haya un fragmento disponible. Cuandocmd1
intenta escribir y ese búfer está lleno, esperará hasta que locmd2
lea.Por lo que puedo leer, no hay necesidad de cortar la entrada en trozos y pasarlos a grep por separado. Eso ya está hecho automáticamente.
EDIT2:
grep
también debe imprimir los resultados tan pronto como los encuentre en la secuencia. No es necesario que la transmisión finalice antes de que pueda obtener sus resultados.fuente
¿Quizás pueda "usar grep en toda la entrada"? ¿Usando
nc
(netcat), o mediantescript
, o mediante otras herramientas similares? Especialmente si su archivo de patrones tiene un tamaño manejable (digamos menos de 1000 expresiones regulares).Primer ejemplo : puede hacer
egrep
alguna conexión de transmisión: (aquí se muestra un ejemplo connc
, pero otros podrían aplicar)(nota: incluso puede:
touch /some/path/results.gz
antes de iniciar elnc
comando, y tenertail -f
en ese archivo (vacío) para no perderse nada. De todos modos, los resultados.gz contendrán todo lo que quería atrapar)segundo ejemplo : incluso podría
egrep
en una sesión de shell actualmente en ejecución (y mostrando otra forma de seguir la progresión):egrep
es una versión altamente eficiente degrep
, en la mayoría de los sistemas (vea algunas informaciones interesantes en: https://swtch.com/~rsc/regexp/regexp1.html )fuente
s
es mucho más lento que hacer coincidirsomething
y esto es mucho más lento que hacer coincidirsomething even much longer
(esto último permite que la coincidencia de expresión regular salte más grande) porciones de la entrada cuando difieren). En archivos grandes, básicamente "divide" el tiempo para analizarlo por la relación de longitud (es decir, agrupar 1 carácter conocido es casi 40 veces más lento que coincidir con una cadena de 40 caracteres conocidos. t prof it pero es realmente notable.)