Corrispondenza più performante di "qualsiasi carattere"


8

Su https://www.emacswiki.org/emacs/MultilineRegexp si trova il suggerimento da usare

[\ 0- \ 377 [: nonascii:]] * \ n

invece dello standard

. * \ N

per far corrispondere qualsiasi carattere a una nuova riga per evitare lo straripamento dello stack per testi enormi (37 KB). L'overflow è la preoccupazione qui, o una corsa corrispondente per la prima è anche più performante della seconda?

Risposte:


9

Nelle regexps di Emacs, .non corrisponde a tutti i personaggi. È sinonimo di [^\n]. Quindi il motivo per usare [\0-\377[:nonascii:]]è quando si desidera abbinare "qualsiasi carattere, anche una nuova riga".

Wrt traboccando lo stack, .*\ndovrebbe essere gestito in modo molto efficiente, cioè senza backtracking e senza divorare lo stack. Al contrario, [\0-\377[:nonascii:]]*\nè gestito in modo piuttosto inefficiente dal motore regexp di Emacs perché consumerà un po 'dello stack per ogni personaggio abbinato, quindi su testi "enormi" tenderà a traboccare lo stack.

Nota che emacswiki suggerisce [\0-\377[:nonascii:]]*e non [\0-\377[:nonascii:]]*\n.


Grazie per il chiarimento. Tuttavia, per l'overflow dello stack, sei sicuro che [\ 0- \ 377 [: nonascii:]] * \ n provocherà un overflow? Questo è il contrario di quanto afferma il wiki. Questo è bcs del \ n alla fine? A che serve un modello come [\ 0- \ 377 [: nonascii:]] * senza un carattere finale?
Vroomfondel,

Qualsiasi regexp che corrisponde a "qualunque cosa" consumerà spazio nello stack (con il motore regexp di Emacs, intendo), e non vedo perché allora [\0-\377[:nonascii:]]*lo farebbe meno \\(.\\|\n\\)*. Quindi penso che emacswiki sia sbagliato su questo.
Stefan,

Qualche modo (o chiunque) di chiarire autorevolmente questo problema?
Vroomfondel,

@Vroomfondel provalo e vedi. Posso immaginare che il regexp con |potrebbe aver bisogno di più backtracking, ma se effettivamente dipende da come è stato compilato.
npostavs,

3
Questo è vero solo se il regexp termina [\0-\377[:nonascii:]]*(il che è piuttosto insolito, dal momento che potresti anche usarlo point-maxpiuttosto che cercarlo tramite tale regexp) (per i curiosi: il punto cruciale della questione è se l'insieme di caratteri che può corrispondere dopo che * è disgiunto dall'insieme di caratteri che può corrispondere a *. Se è disgiunto, il motore regexp salterà la registrazione di passaggi intermedi, evitando quindi di consumare spazio nello stack. Quindi .*\ne [^a]*anon consumare lo stack, mentre .*alo fa).
Stefan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.