Page 1 sur 2

Regex for comment-line

Posté : mar. 05 juil. 2016 08:58
par mdanielm
Salut,
Pour me faciliter la traduction des commentaires des exemples de la documentation AutoIt, j'aurais besoin d'une regex qui capture les comment-line dans du code au3 (supposé syntaxiquement correct).
J'ai déjà trouvé une regex qui matche les comment-block, on pourra donc supposer que le code au3 n'en contient pas.

Match:
; "Comment-line"
$x='' ; chaîne "vide"
$x = "aa;aa" ; Comment-line
$x = "a" ;$x='b'

No match:
$x = 'bb;b'
$x = " " & "bb"

Aide: pour capturer des chaînes, éventuellement dans des commentaires, j'ai ça:
(
(?:"[^"\r]*(?:""[^"\r]*)*")
|
(?:'[^'\r]*(?:''[^'\r]*)*')
)

(qui semble convenir!)

Re: Regex for comment-line

Posté : mar. 05 juil. 2016 15:14
par orax
Il y a peut-être tout ceci dans les scripts qui servent à générer la doc. Je pense que ça doit se trouver dans les scripts du dossier docs\_build (autoit-docs-v3.3.14.2-src.zip\docs\_build).

-----

J'ai un peu cherché, mais pour l'instant je n'ai rien trouvé, à part ce lien (trouvé dans le fichier docs\_build\include\MiscLib.au3).

Re: Regex for comment-line

Posté : mar. 05 juil. 2016 16:26
par mdanielm
Merci,
Je vais regarder.
...
Semble convenir:
\r\n # fin de ligne précédente: petit problème sur la 1ere ligne
[^;"'\r\n]* # des car autre que [;"'\r\n]

(?: # pas de capture
[^;"'\r\n] # 1 car autre que [;"'\r\n] Pourquoi cette répétition?
| # ou
'[^'\r\n]*' # car ' suivi de car autre que ['\r\n]
| # ou
"[^"\r\n]*" # car " suivi de car autre que ["\r\n]
)* # 0 ou plus

\K # Réinitialise la recherche à cet endroit. Utile?
(;[^\r\n]*) # capture car ; suivi de car autre que [\r\n]

Re: Regex for comment-line

Posté : mar. 05 juil. 2016 18:12
par orax
https://regex101.com/r/jS5bK7/3

Code : Tout sélectionner

(?xm)^
(?:|
  [^;"'\r\n]*
  (?:
    (?:'[^'\r\n]*')|
    (?:"[^"\r\n]*")
  )*
)
\h*\K
(;[^\r\n]*)
Il faut quand même vérifier qu'elle fonctionne correctement.

Re: Regex for comment-line

Posté : mar. 05 juil. 2016 22:41
par jguinch
Un poil plus court peut-être :
https://regex101.com/r/jS5bK7/4

Code : Tout sélectionner

(?:
   "[^"\r\n]*" |
   '[^'\r\n]*' |
   [^;]
)*
(;\N+)?

Re: Regex for comment-line

Posté : mar. 05 juil. 2016 22:56
par mdanielm
Merci pour vos indications.
Je pense tenir maintenant un algorithme pour colorer du code au3.

Re: Regex for comment-line

Posté : mar. 05 juil. 2016 23:07
par orax
\K # Réinitialise la recherche à cet endroit. Utile?
Non, ce n'est pas nécessaire. D'ailleurs, je l'avais supprimé sur regex101.com.

Re: Regex for comment-line

Posté : mar. 05 juil. 2016 23:22
par mdanielm
JGuinch, je crois que cette solution a un problème, peut-être le \N+.
Essaie avec:

$x = 'bb;b'
$x = "bb;b"
$x = " " & "bb"

Testé avec PCRE Toolkit.

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 04:13
par jchd
Et ça, ça irait ?

Code : Tout sélectionner

(?|[^";]*"[^"]*+"|[^';]*'[^']*+')*+[^"';]*(;.*)

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 08:07
par mdanielm
Non, pas davantage, jchd!

Testé avec pcre toolkit et les exemples suivants:

$x = 'bb;b'
$x = "bb;b"
$x = " " & "bb"

Orax, ta solution non plus:

$x = "a" & "b" ; com

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 13:27
par jguinch
Deuxième tentative :

Code : Tout sélectionner

(?:'.*?'|".*?"|[^;'"\r\n])*(;\N*)?

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 13:30
par orax
Le groupe (?: ... ) est censé être non capturant.
Je pensais que le code suivant allait me retourner une erreur, mais il affiche "b".

Code : Tout sélectionner

$a = StringRegExp("abc", "(?:b)", 3)
ConsoleWrite($a[0] & @CRLF) ; affiche "b"

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 13:38
par jguinch
Par défaut, si aucun groupe capturant n'est spécifié, AutoIt considère qu'il faut tout capturer

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 14:11
par mdanielm
Jguinch, 2-ième tentative, global match:

Test:
$x = "a" & "b" ; com
$x = "a;a" ;a
$x = "b;b" ;b
$x=1;

Résultats:
[0] = ; com
[1] =
[2] = ;a
[3] =
[4] = ;b
[5] =
[6] = ;
[7] =
[8] =

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 17:00
par jchd
Oups, voyons si je suis plus inspiré comme ça :

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 & _
	";No match:" & @CRLF & _
	"$x = 'bb;b'" & @CRLF & _
	'$x = " " & "bb"           ;;ccc'

Local $a = StringRegExp($s, "(?mx)^(?:[^""';]*+(?:(?:"".*?"")++|(?:'.*?')++)?)*+[^;]*(;.*)$", 3)
_ArrayDisplay($a)

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 19:25
par orax
J'ai un peu corrigé l'expression régulière que j'avais faite et j'ai aussi créé des tests unitaires (sur regex101) pour vérifier plus facilement si l'expression est correcte : https://regex101.com/r/lZ6oV9/1 (dans "unit tests" à gauche).

Pour pouvoir réutiliser les tests créés dans regex101 dans le but de vérifier que ça fonctionne aussi avec StringRegExp(), j'ai créé le script ci-dessous (vite fait et expérimental). Il suffit de copier-coller le texte de "unit tests" dans le script (le texte copié doit être placé entre #cs et #ce).
Ça ne marche que pour assert that capture group 1 equals et assert that regex does not match', mais c'était suffisant dans mon cas.
Si rien ne s'affiche dans la console, alors tous les tests passent sans erreur.
; expression à tester
$regex = '(?xm)^(?:  [^;"'']+  (?:    (?:''[^'']*'')|    (?:"[^"]*")  )*)*+(;\N+)'

; récupère la liste des tests unitaires
$s = StringRegExp(FileRead(@ScriptFullPath), '(?ms)^#cs\s*(.+?)\s*^#ce', 1)[0]
$s = StringRegExpReplace($s, '(?m)^\s+', '')

; le groupe 1 doit être égal à...
$a = StringRegExp($s, '(?m)^given the string\t(.+?)   assert that capture group 1   equals   (.+)', 3)
For $i = 0 To UBound($a) - 1 Step 2
   $aResult = StringRegExp($a[$i], $regex, 1)
   If IsArray($aResult) Then
      If $aResult[0] <> $a[$i + 1] Then ConsoleWriteError("! __" & $a[$i] & "__ - " & $aResult[0] & ' <> ' & $a[$i + 1] & @CRLF)
   Else
      ConsoleWriteError("! __" & $a[$i] & "__ - Chaîne __" & $a[$i + 1] & "__ non trouvée." & @CRLF)
   EndIf
Next

; la chaîne ne doit pas être trouvée
$a = StringRegExp($s, '(?m)^given the string\t(.+?)   assert that regex does not match', 3)
For $i = 0 To UBound($a) - 1
   $aResult = StringRegExp($a[$i], $regex, 1)
   If IsArray($aResult) Then
      ConsoleWriteError("! Chaîne __" & $a[$i] & "__ trouvée." & @CRLF)
   EndIf
Next

; liste des tests unitaires sur regex101.com (liste copiée depuis "unit tests" > "TEST LIST")
#cs
given the string  ;test    assert that    capture group 1   equals   ;test
given the string  $x = 'bb;b'    assert that    regex    does not match
given the string  $x = "&nbsp;" & "bb"           ;;ccc   assert that    capture group 1   equals   ;;ccc
given the string  $x = "a''a;a""a" ; Comment-line  assert that    capture group 1   equals   ; Comment-line
given the string  $x = "&nbsp;" & "bb"    assert that    regex    does not match
given the string  $x = "bb;b"    assert that    regex    does not match
given the string  $x = 'bb;b'    assert that    regex    does not match
given the string  $x = "a" & "b" ; com    assert that    capture group 1   equals   ; com
given the string      ; test  assert that    capture group 1   equals   ; test
given the string   ; test  assert that    capture group 1   equals   ; test
given the string  ; ; ;";'    assert that    capture group 1   equals   ; ; ;";'
given the string  ;;;;  assert that    capture group 1   equals   ;;;;
given the string  $x=" ' ';' "";"" ""' '"" ""'""" ; chaîne 'vide'   assert that    capture group 1   equals   ; chaîne 'vide'
given the string  $x=" ' ';' "";"" ""' '"" ""'""" ; chaîne "vide"   assert that    capture group 1   equals   ; chaîne "vide"
given the string  $x="" ; chaîne "vide"  assert that    capture group 1   equals   ; chaîne "vide"
given the string  $x='' ; chaîne "vide"  assert that    capture group 1   equals   ; chaîne "vide"
given the string  ; 'test"    assert that    capture group 1   equals   ; 'test"
given the string  ; 'test'    assert that    capture group 1   equals   ; 'test'
given the string  ; "test'    assert that    capture group 1   equals   ; "test'
given the string  ; "test"    assert that    capture group 1   equals   ; "test"
given the string  ; test   assert that    capture group 1   equals   ; test
given the string  $x=' '' '';'' ";" "'' ''" "''"' ; chaîne "vide"   assert that capture group 1   equals   ; chaîne "vide"
given the string  $x=' '' '';'' ";" "'' ''" "''"' ; chaîne 'vide'   assert that capture group 1   equals   ; chaîne 'vide'
given the string  $x = "a" ;$x='b'  assert that capture group 1   equals   ;$x='b'
given the string  $x = "aa;aa" ; Comment-line   assert that capture group 1   equals   ; Comment-line
given the string  $x="" ; chaîne 'vide'  assert that capture group 1   equals   ; chaîne 'vide'
#ce
La dernière expression régulière de jchd passe également tous les tests.

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 20:03
par mdanielm
Cette fois c'est ok, solution orax et jchd .
Merci pour le temps passé dessus, mais bon, c'est plus marrant que sudoku!

Re: Regex for comment-line

Posté : mer. 06 juil. 2016 20:32
par jguinch
@jc : j'ai essayé ta regex sur regex101, mais je crois qu'il y a un petit oubli quelque part (j'ai pas pris le temps de regarder) :
https://regex101.com/r/dP8lY8/1


Euuh, non j'ai rien dit (j'ai recopié bêtement la regex sans faire attention à l'échappement des doubles quotes ...

Re: Regex for comment-line

Posté : jeu. 07 juil. 2016 00:15
par orax
jguinch a écrit :Par défaut, si aucun groupe capturant n'est spécifié, AutoIt considère qu'il faut tout capturer
Je pense que c'est pour cette raison que les regex de JGuinch fonctionnent correctement sur regex101, mais que le résultat est différent sur PCRE Toolkit.
En ajoutant un \K je pense que ça pourrait solutionner le problème.

Code : Tout sélectionner

(?:"[^"\r\n]*"|'[^'\r\n]*'|[^;])*\K(;\N+)?

(?:'.*?'|".*?"|[^;'"\r\n])*\K(;\N*)?

Re: Regex for comment-line

Posté : jeu. 07 juil. 2016 09:22
par jguinch
ma dernière regex générait des lignes blanches à juste titre.
J'avais mis (;\N*)?, qui fait que chaque ligne va générer une capture (une chaine vide sera capturer sur les lignes qui ne contiennent pas de commentaire.
Il faut remplacer par ;(\N*)?, qui rend le ";" obligatoire, du coup, à pu les captures vides.