Page 1 sur 1

Regex for comments-block

Posté : dim. 10 juil. 2016 20:09
par mdanielm
En voilà une qui convenait:

(?ims)(^\h*#(?:cs|comments-start)(?!\w).+?#(?:ce|comments-end)[^\r\n]*)(?:\R|$)

...avant que je me souvienne de la doc:
"Les instructions #comments-start et #comments-end peuvent être imbriquées."

Dans ce cas elle ne convient plus!
Quelqu'un a une idée ?
Exemple:

#commentS-start com1
com2
#cs com3
com4
#ce com5
#coMMents-end com6

Bonne finale!

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 01:11
par orax
https://regex101.com/r/dJ7xH7

Code : Tout sélectionner

(?msx)
^\h*\#(?:cs|comments-start)\h*.+?\R+

(?:
  [^\#] | \#(?!cs|ce|comments-start|comments-end)
|
  (?R)
)*

^\h*\#(?:ce|comments-end)
Je n'ai pas encore vérifié si ça fonctionne vraiment correctement. Et on peut sans doute faire mieux, elle n'est peut-être pas très optimisée.

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 08:16
par mdanielm
Bonjour,
Je crois que non, la recherche s'arrête au premier #ce rencontré.
Je l'ai testé en situation: dans mon script.
J'ai rajouté une capture car je veux encadrer le bloc par des balises <span...

(?msx)
^\h* (\#(?:cs|comments-start)\h*.+?\R+

(?:
[^\#] | \#(?!cs|ce|comments-start|comments-end)
|
(?R)
)* )

J'ai déjà une solution à mon problème mais elle tient sur 18 lignes avec 2 while imbriqués.
Je me demandais comment utiliser la récursivité dans une regex.
Merci

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 10:40
par jchd
Tout à fait :

Code : Tout sélectionner

(?imsx)
(?(DEFINE) (?<CSline> ^ \h* \# (?: cs | comments-start ) \b \N* \R ) )
(?(DEFINE) (?<CEline> ^ \h* \# (?: ce | comments-end ) \b \N* \R ) )
(?(DEFINE) (?<Comment> ^ \N*? (?! (?&CSline) | (?&CEline) ) \R ) )
(?(DEFINE) (?<Cblock> (?&CSline) (?: (?&Cblock)* | (?&Comment)*? )* (?&CEline) ) )
(
  (?&Cblock)
)
L'emploi de (?(DEFINE) ...) n'est là que pour clarifier la structure de l'expression. On peut évidemment faire tout ça "inline", mais c'est un brin indigeste. Certes ça crée un peu de backtracking mais c'est tellement plus clair !

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 14:53
par mdanielm
Cette fonctionnalité semble très intéressante.
Lorsque j'utilise votre regex comme çi-dessous, les blocs de commentaires disparaissent et sont remplacés par:
<span class="S2"></span>
Sans doute un problème de capture?
func CommentBlock(byref $data) ;style "S2"
   ; JCHD
Local $regex = _
'(?imsx)' & _
'(?(DEFINE) (?<CSline> ^ \h* \# (?: cs | comments-start ) \b \N* \R ) )' & _
'(?(DEFINE) (?<CEline> ^ \h* \# (?: ce | comments-end ) \b \N* \R ) )' & _
'(?(DEFINE) (?<Comment> ^ \N*? (?! (?&CSline) | (?&CEline) ) \R ) )' & _
'(?(DEFINE) (?<Cblock> (?&CSline) (?: (?&Cblock)* | (?&Comment)*? )* (?&CEline) ) )' & _
'(' & _
'  (?&Cblock)' & _
')'

$data = StringRegExpReplace($data, $regex, '<span class="S2">\1</span>')

EndFunc

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 15:40
par jguinch
Remplace \1 par \5 dans le remplacement

Edit : super cette regex JC. Ca donne un bon exemple d'utilisation de la récursivité

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 16:53
par jchd

Code : Tout sélectionner

Local $s = _
	'; "Comment-line"' & @CRLF & _
	"$x='' ; chaîne ""vide""" & @CRLF & _
	'$x = "a''''a;a""a" ; Comment-line' & @CRLF & _
	"y'a rien à voir ici" & @CRLF & _
	"$x = ""a"" ;$x='b'" & @CRLF & _
	"" & @CRLF & _
	"$x=""a""&';b'" & @CRLF & _
	"#cs xyz" & @CRLF & _
	"  gna" & @CRLF & _
	"#cs xyz" & @CRLF & _
	"  gna gna" & @CRLF & _
	"#ce xyz" & @CRLF & _
	"#ce xyz" & @CRLF & _
	";No match:" & @CRLF & _
	"$x = 'bb;b'" & @CRLF & _
	"#cs xyz" & @CRLF & _
	"  gna gna" & @CRLF & _
	"#ce xyz" & @CRLF & _
	'$x = "&nbsp;" & "bb"           ;;ccc'

CommentBlock($s)
ConsoleWrite($s & @LF)

Func CommentBlock(byref $data) ;style "S2"
    ; JCHD
	Local $regex = _
		'(?imsx)' & _
		'(?(DEFINE) (?<CSline> ^ \h* \# (?: cs | comments-start ) \b \N* \R ) )' & _
		'(?(DEFINE) (?<CEline> ^ \h* \# (?: ce | comments-end ) \b \N* \R ) )' & _
		'(?(DEFINE) (?<Comment> ^ \N*? (?! (?&CSline) | (?&CEline) ) \R ) )' & _
		'(?(DEFINE) (?<Cblock> (?&CSline) (?: (?&Cblock)* | (?&Comment)*? )* (?&CEline) ) )' & _
		'(' & _
		'   (?&Cblock)' & _
		')'
    $data = StringRegExpReplace($data, $regex, '<span class="S2">$0</span>')
EndFunc

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 19:49
par mdanielm
Génial!
C'était donc \0 ou \5 mais pas \1 !
Je vais essayer de placer ma balise ouvrante immédiatement avant #cs et pas en début de ligne et la fermante en fin de ligne #ce et pas au début de la ligne suivante, ça me semble plus logique.
Bonsoir

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 20:03
par jguinch
@JC : si tu peux m'éclairer un peu : j'ai jamais vraiment compris à quoi sert le fameux $0...

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 20:12
par jchd
Daniel,
Ca peut s'avérer un poil plus sportif ! Je pense que ça sera plus facile avec un enrobage Execute et une imbricatrion de String*** dans la partie Replace. Sinon je ne vois pas trop comment faire ça proprement pour que ça fonctionne dans tous les cas. Je n'ai pas non plus trop le temps de creuser plus avant.

jguinch,
Faudrait demander à Jon, ou déterminer ça comme je fais, par tâtonnement et déduction... La version *Replace est une création qui n'a pas d'équivalent dans la bibliothèque PCRE, donc d'implémentation libre.

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 21:02
par orax
L'expression régulière de jchd fonctionne très bien, mais j'ai quand même voulu essayé de corriger la mienne pour mieux comprendre mes erreurs. Donc voilà la v2 (qui semble mieux fonctionner) : https://regex101.com/r/dJ7xH7/2

Code : Tout sélectionner

(?imx)
^\h*\# (?>cs|comments-start) (?:\h\N*|$) \R

(?:
  (?!\h*\# (?>cs|comments-start|ce|comments-end) (?:\h|$) ) \N*\R
|
  (?R)
)*

\h*\# (?>ce|comments-end) (?:\h\N*|$) \R?

En exportant un fichier HTML depuis SciTE, j'ai remarqué que le code est très lourd. Par exemple, pour chaque ligne commentée il ajoute un <span class="S2">. Je ne pense pas que ce soit nécessaire. On pourrait aussi utiliser <pre> plutôt que de mettre plein de &nbsp;.
D'après moi, le code...
<span class="S2">&nbsp;&nbsp;gna</span><br />
<span class="S2">#cs xyz</span><br />
<span class="S2">&nbsp;&nbsp;gna gna</span><br />
<span class="S2">#ce xyz</span><br />
<span class="S2">#ce xyz</span><br />
pourrait être simplifié par :
<pre><code><span class="S2">  gna<br>
#cs xyz<br>
  gna gna<br>
#ce xyz<br>
#ce xyz<br></span></pre></code>

Si $0 ou \0 est utilisé (au lieu de $5 ou \5), il n'y a pas besoin de capturer (?&Cblock) dans un groupe numéroté, me semble-t-il.
Au lieu de mettre...

Code : Tout sélectionner

'(' & _
'   (?&Cblock)' & _
')'
... le code suivant suffirait, non ?

Code : Tout sélectionner

(?&Cblock)' & _

jguinch,
Je ne sais pas si j'ai bien compris ta question, mais, pour moi, $0 ou \0 représente tout ce qui a été trouvé depuis le début ou depuis le dernier \K, même si la chaîne est dans un groupe non capturant comme (?: ... ).
[codeautoit]ConsoleWrite(StringRegExpReplace("abcdef", "cd", "*\0*") & @CRLF) ; ab*cd*ef
ConsoleWrite(StringRegExpReplace("abcdef", "(?:cd)", "*\0*") & @CRLF) ; ab*cd*ef
ConsoleWrite(StringRegExpReplace("abcdef", "c\Kd", "*\0*") & @CRLF) ; abc*d*ef[/codeautoit]

Re: Regex for comments-block

Posté : lun. 11 juil. 2016 21:06
par jguinch
Oui, tu as bien compris ma question, et parfaitement répondu à ma question (avec un exemple en plus). Merci :wink:

Re: Regex for comments-block

Posté : mar. 12 juil. 2016 08:29
par mdanielm
@Orax,
Ta version 2 convient mais je ne comprends pas la logique pour le moment
Avec la regex de jchd, je comprends la logique globale, bien que:
(?<Comment> ^ \N*? (?! (?&CSline) | (?&CEline) ) \R ) )
supporterait une explication pour moi.
look-ahead négatif : contre-sens, peut-être look-ahead par négation?

Une traduction en français aiderait:
"n'importe quoi sauf @crlf répété 0 ou plus mais aussi peu que possible, et NON suivi de CSline, ni de CEline, et terminé par \r\n"

C'est de cette façon qu'il faut traduire?

Re: Regex for comments-block

Posté : mar. 12 juil. 2016 10:23
par jchd
Oui, je pense que c'est une définition correcte de toute ligne qui est à l'intérieur d'un block #cs ... #ce et qui n'est ni un #ce ni un nouveau #cs puisqu'ils peuvent être imbriqués.

Re: Regex for comments-block

Posté : mar. 12 juil. 2016 12:20
par mdanielm
Je viens de comprendre la signification de
?!
look ahead négationnel (..si l'adjectif existe!)
Regarder devant, comme je lis de gauche à droite, je pensais 'regarder après' alors qu'en fait c'est regarder précédemment.
Du coup je comprends ta définition de 'comment'.
La doc AutoIt manque cruellement d'exemples.

Re: Regex for comments-block

Posté : jeu. 14 juil. 2016 22:02
par orax
mdanielm a écrit :Je vais essayer de placer ma balise ouvrante immédiatement avant #cs et pas en début de ligne et la fermante en fin de ligne #ce et pas au début de la ligne suivante, ça me semble plus logique.
Les deux solutions ci-dessous devraient convenir.
J'ai essayé de le faire avec la regex de JCHD et la mienne.
► Afficher le textevoir les regex

Re: Regex for comments-block

Posté : jeu. 14 juil. 2016 22:55
par mikell
jguinch
$0 est un truc batard apparemment propre à Autoit qui permet de retourner une backreference correspondant au pattern sans groupe capturant

Code : Tout sélectionner

    ConsoleWrite(StringRegExpReplace("abcdef", "cd", "*\0*") & @CRLF)     ; ab*cd*ef
    ConsoleWrite(StringRegExpReplace("abcdef", "(cd)", "*\0*") & @CRLF)     ; ab*cd*ef
    ConsoleWrite(StringRegExpReplace("abcdef", "(cd)", "*\1*") & @CRLF)     ; ab*cd*ef
    ConsoleWrite(StringRegExpReplace("abcdef", "b(cd)", "*\0*") & @CRLF)     ; a*bcd*ef
    ConsoleWrite(StringRegExpReplace("abcdef", "b(cd)", "*\1*") & @CRLF)     ; a*cd*ef
étonnant non ? :mrgreen: