Estou usando o egrep ( grep -E
) com um arquivo PATTERN. ( -f path/to/file
)
Isso é feito em um loop infinito em um fluxo de texto. Isso implica que eu não posso acumular e passar TODA a entrada para grep de uma só vez (como *.log
).
Existe uma maneira de fazer grep "salvar" o NFA que está construindo a partir do arquivo PATTERN para usar na próxima execução?
Pesquisei no Google e li a documentação sem sorte.
Vou tentar explicar um pouco mais. Preciso localizar um número fixo de strings com expressões regulares (isso não faz parte de uma pergunta, mas fique à vontade para sugerir o contrário), como endereços IP, domínios etc. A pesquisa é feita em um feed da Internet. Você pode pensar nisso como um fluxo de texto. Não posso usar grep
todas as entradas, pois é um fluxo. Posso acumular um pedaço de fluxo e usá grep
-lo (portanto não o uso grep
em cada linha), mas isso também é limitado (digamos, por 30 segundos).
Eu sei que grep
está criando um NFA a partir de todos os seus padrões (no meu caso, a partir de um arquivo). Então, minha pergunta aqui é: posso dizer grep
para salvar esse NFA para a próxima execução, pois não vai mudar? Isso me pouparia o tempo de construir essa NFA todas as vezes.
grep
por linha de texto? De onde vem o texto? Seriatail -f
uma opção?grep
nesse pedaço.grep
várias vezes. Possivelmente relacionado: por que a correspondência de 1250 strings e 90k de padrões é tão lenta?grep
se destina a trabalhar em um fluxo de texto, ainda não entendi por que você precisaria executar várias instâncias. Por que você não pode alimentar tudo isso na mesmagrep
instância? Por que você precisa acumulá- los antes de alimentargrep
?Respostas:
Não, não existe. Geralmente, o custo de inicialização
grep
(bifurcar um novo processo, carregar a biblioteca executável, compartilhada, ligação dinâmica ...) seria muito maior do que compilar os regexps; portanto, esse tipo de otimização faria pouco sentido.Embora veja Por que a correspondência de 1250 strings e 90k de padrões é tão lenta? sobre um bug em algumas versões do GNU
grep
que o tornaria particularmente lento para um grande número de regexps.Possivelmente aqui, você pode evitar executar
grep
várias vezes alimentando seus pedaços na mesmagrep
instância, por exemplo, usando-o como um co-processo e usando um marcador para detectar o fim. Comzsh
e GNUgrep
eawk
implementações diferentes demawk
:Embora possa ser mais simples fazer tudo com
awk
ouperl
não.Mas se você não precisa que a
grep
saída entre em arquivos diferentes para diferentes pedaços, você sempre pode:fonte
grep
como está. Obrigado.Você sabe que os dutos bloqueiam? Se você canalizar algo para grep e toda a entrada não estiver disponível, o grep aguardará até que esteja disponível e continuará como se a entrada estivesse lá o tempo todo.
EDIT: Como os pipelines funcionam, por exemplo,
cmd1 | cmd2
é que ambos os programas serão iniciados ao mesmo tempo, com um "buffer de bloco" de 65.536 bytes entre eles. Quandocmd2
tenta ler e esse buffer está vazio, ele espera um pedaço estar disponível. Quandocmd1
tenta gravar e esse buffer estiver cheio, ele aguardará até que sejacmd2
lido.Pelo que posso ler, não há necessidade de cortar a entrada em pedaços e passá-los para grep separadamente. Isso já é feito automaticamente.
EDIT2:
grep
também deve imprimir os resultados assim que os encontrar no fluxo. Não há necessidade de o fluxo terminar antes que você possa obter seus resultados.fonte
Talvez você possa "usar grep em todas as entradas"? Usando
nc
(netcat), ou através descript
, ou através de outras ferramentas similares? Especialmente se o seu arquivo de padrão for de tamanho gerenciável (digamos, menos de 1000 regexps).Primeiro exemplo : você pode fazer
egrep
uma conexão de streaming: (aqui exemplo mostrado comnc
, mas outros podem ser aplicáveis)(note: você pode até:
touch /some/path/results.gz
antes de iniciar onc
comando, e tertail -f
nesse arquivo (vazio) para não perder nada. Enfim, o results.gz conterá tudo o que você deseja capturar)segundo exemplo : você pode até mesmo
egrep
em uma sessão de shell em execução no momento (e mostrando outra maneira de acompanhar a progressão):egrep
é uma versão altamente eficiente degrep
, na maioria dos sistemas (consulte algumas informações interessantes em: https://swtch.com/~rsc/regexp/regexp1.html )fonte
s
é muito, mais lento que o casamentosomething
e isso é muito mais lento que o casamentosomething even much longer
(este último permite que o casamento do regexp pule maior em arquivos grandes, basicamente "divide" o tempo para analisá-lo pela proporção de comprimento (por exemplo, grepping 1 caractere conhecido é quase 40 vezes mais lento do que corresponder a uma sequência de 40 caracteres conhecidos. t prof isso, mas é realmente perceptível).