Je te propose une solution que je qualifierais pour l'instant de théorique (car pas testée en situation réelle avec la longueur de ton texte).
Elle consiste à utiliser une capture de la fin du texte suite à l'une des deux conditions pour contraindre l'autre condition qui doit vérifier que la partie capturée est bien à sa suite. Concrètement ça donne ça:
~(*napla:.{1,300}$\R?(.*\z))(?>\N*\R?){0,5}(?=\1)~ums
demo
L'astuce consiste ici à placer l'une des conditions dans un test avant non-atomique (non-atomic positive lookahead, soit "napla"). Contrairement à test avant normal qui lui est naturellement atomique (le moteur de regex ne reviendra pas pour tester d'autres possibilités pour la sous pattern contenue dans cette assertion), le test avant non-atomique permet d'essayer plusieurs possibilités. Donc si après (?>\N*\R?){0,5}, la fin du texte est différente que celle capturée par (.*\z), autrement dit si (?=\1) échoue, le moteur de regex amorcera son backtracking qui pourra aller jusqu'à réduire le nombre de caractères consommés par .{1,300} pour tester une autre possibilité.
Si du fait du nombre de caractères en situation réelle cette solution devait échouer, je te conseille de lire 300 caractères, de compter les sauts de lignes, puis au cas où de scinder au 5e saut de ligne pour adjoindre le reste à la prochaine lecture, le tout en bon vieux code.
NB: tu peux avantageusement remplacer .{1,300} (qui consommera de 1 à 300 points de code) par \X{1,300} (qui consommera de 1 à 300 graphèmes). En effet, un caractère suivie d'un ou plusieurs caractères combinants (comme une lettre suivie de ses accents par exemple) comptera pour plus d'un point de code, mais ne comptera que pour un seul graphème.
Pour augmenter la scalabilité de la pattern, tu peux éventuellement faire le pari que les 1000 ou 10000 prochains caractères suivant une condition ne seront jamais les mêmes et remplacer .*\z par .{0,10000}+, ce qui évite au moteur de regex d'aller jusqu'à la fin du texte. (Le gain de temps est considérable si le texte est long)
1 2 3 4
| ~(*ANYCRLF)(*BSR_ANYCRLF)
(?* \X{1,300} $ \R? (.{0,10000}+) )
(?> \N* \R? ){1,5} (?=\1)
~umsx |
demo 2
Partager