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" ; JCHDLocal $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 = " " & "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 .
D'après moi, le code...
pourrait être simplifié par :
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...
... le code suivant suffirait, non ?
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

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
https://regex101.com/r/dA0nV5/11
(?imx)
(?(DEFINE) (?<CSline> \h* \# (?: cs | comments-start ) \b\N*\R ) )
(?(DEFINE) (?<CEline> ^\h* \# (?: ce | comments-end ) ) )
(?(DEFINE) (?<Comment> ^\N*? (?! ^ (?&CSline) | (?&CEline) \b\N*\R ) \R ) )
(?(DEFINE) (?<Cblock>
(?&CSline)
(?: (?&Cblock)* | (?&Comment)*? )*
(?&CEline) \b\N*\R ) )
( ^\h* ) ( (?&CSline) (?: (?&Cblock)* | (?&Comment)*? )* (?&CEline) \b\N*? ) ( \h*+ $ \R? )
https://regex101.com/r/dJ7xH7/5
(?imx)
(^\h*) # capture les espaces avant #cs (ex. < >#cs)
(
\# (?> cs|comments-start ) \b\N*\R # => #cs
# => commentaires (partie entre #cs et #ce)
(?:
# vérifie qu'il s'agit bien d'un commentaire
# c.-à-d. que le début de la ligne NE doit PAS être suivi par ce qui
# correspond à un début (#cs) ou fin de commentaire (#ce)
(?!
\h* \# (?> cs|comments-start|ce|comments-end ) \b\N*\R
)
# le commentaire
# un commentaire peut simplement être une nouvelle ligne (\R)
\N*\R
| # commentaire ou récursion (si aucun commentaire trouvé)
# récursion (depuis le début) pour chercher un nouveau #cs
(?R)
)* # les commentaire sont facultatifs
\h* \# (?> ce|comments-end ) # => #ce
\b\N*? # texte après #ce, facultatif (ex. #ce< TEXTE>)
)
# capture, s'il y en a, les espaces et la fin de ligne après #ce (ex. #ce blabla...< \R>)
(
\h*+ $ # espaces après #ce ; seulement ceux avant la fin de ligne (ex. #ce blabla...< >$)
\R? # retour à la ligne facultatif
)
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 ?
