grex est une bibliothèque ainsi qu'un utilitaire de ligne de commande destiné à simplifier la tâche souvent compliquée et fastidieuse de création d'expressions régulières. Pour ce faire, il génère automatiquement une seule expression régulière à partir des cas de test fournis par l'utilisateur. L'expression résultante est garantie de correspondre aux cas de test à partir desquels elle a été générée.
Ce projet a démarré en tant que portage Rust de l'outil JavaScript regexgen écrit par Devon Govett. Bien que de nombreuses autres fonctionnalités utiles pourraient y être ajoutées, son développement a apparemment été interrompu il y a plusieurs années. Le plan est maintenant d'ajouter ces nouvelles fonctionnalités à grex, car Rust brille vraiment en matière d'outils de ligne de commande. grex offre toutes les fonctionnalités fournies par regexgen , et plus encore.
La philosophie de ce projet est de générer par défaut l'expression régulière la plus spécifique possible qui correspond exactement à l'entrée donnée et rien d'autre. Avec l'utilisation d'indicateurs de ligne de commande (dans l'outil CLI) ou de méthodes de prétraitement (dans la bibliothèque), des expressions plus généralisées peuvent être créées.
Les expressions produites sont des expressions régulières compatibles Perl qui sont également compatibles avec l'analyseur d'expressions régulières dans la caisse d'expressions régulières de Rust. D'autres analyseurs d'expressions régulières ou bibliothèques respectives d'autres langages de programmation n'ont pas été testés jusqu'à présent, mais ils devraient également être pour la plupart compatibles.
Certainement, oui ! En utilisant les paramètres standard, grex produit une expression régulière qui garantit qu'elle correspondra uniquement aux cas de test donnés en entrée et à rien d'autre. Cela a été vérifié par des tests de propriété. Cependant, si la conversion en classes de caractères abrégés telles que w
est activée, l'expression régulière résultante correspond à une portée beaucoup plus large de cas de test. Connaître les conséquences de cette conversion est essentiel pour trouver une expression régulière correcte pour votre domaine métier.
grex utilise un algorithme qui tente de trouver l'expression régulière la plus courte possible pour les cas de test donnés. Mais très souvent, l’expression qui en résulte est encore plus longue ou plus complexe qu’elle ne devrait l’être. Dans de tels cas, une expression régulière plus compacte ou élégante ne peut être créée qu’à la main. De plus, chaque moteur d'expression régulière possède différentes optimisations intégrées. grex n'en sait rien et ne peut donc pas optimiser ses expressions rationnelles pour un moteur spécifique.
Alors, s'il vous plaît, apprenez à écrire des expressions régulières ! Le meilleur cas d'utilisation actuel de grex est de trouver une expression régulière correcte initiale qui doit être inspectée manuellement si d'autres optimisations sont possibles.
{min,max}
|
opérateur?
quantificateur^
et $
Vous pouvez télécharger ci-dessus l'exécutable autonome pour votre plateforme et le placer à l'endroit de votre choix. Alternativement, des binaires 64 bits précompilés sont disponibles dans les gestionnaires de packages Scoop (pour Windows), Homebrew (pour macOS et Linux), MacPorts (pour macOS) et Huber (pour macOS, Linux et Windows). Raúl Piracés a contribué à un package Chocolatey Windows.
grex est également hébergé sur crates.io, le registre officiel des packages Rust. Si vous êtes un développeur Rust et que la chaîne d'outils Rust est déjà installée, vous pouvez l'installer en compilant à partir des sources à l'aide de cargo , le gestionnaire de packages Rust. Le résumé de vos options d'installation est donc :
( brew | cargo | choco | huber | port | scoop ) install grex
Afin d'utiliser grex comme bibliothèque, ajoutez-le simplement comme dépendance à votre fichier Cargo.toml
:
[ dependencies ]
grex = { version = " 1.4.5 " , default-features = false }
Le clap de dépendance n'est nécessaire que pour l'outil de ligne de commande. En désactivant les fonctionnalités par défaut, le téléchargement et la compilation de clap sont empêchés pour la bibliothèque.
Des explications détaillées sur les paramètres disponibles sont fournies dans la section bibliothèque. Tous les réglages peuvent être librement combinés entre eux.
Les cas de test sont transmis soit directement ( grex abc
) soit à partir d'un fichier ( grex -f test_cases.txt
). grex est également capable de recevoir ses entrées des pipelines Unix, par exemple cat test_cases.txt | grex -
.
Le tableau suivant présente tous les indicateurs et options disponibles :
$ grex -h
grex 1.4.5
© 2019-today Peter M. Stahl
Licensed under the Apache License, Version 2.0
Downloadable from https://crates.io/crates/grex
Source code at https://github.com/pemistahl/grex
grex generates regular expressions from user-provided test cases.
Usage: grex [OPTIONS] {INPUT...|--file }
Input:
[INPUT]... One or more test cases separated by blank space
-f, --file Reads test cases on separate lines from a file
Digit Options:
-d, --digits Converts any Unicode decimal digit to d
-D, --non-digits Converts any character which is not a Unicode decimal digit to D
Whitespace Options:
-s, --spaces Converts any Unicode whitespace character to s
-S, --non-spaces Converts any character which is not a Unicode whitespace character to S
Word Options:
-w, --words Converts any Unicode word character to w
-W, --non-words Converts any character which is not a Unicode word character to W
Escaping Options:
-e, --escape Replaces all non-ASCII characters with unicode escape sequences
--with-surrogates Converts astral code points to surrogate pairs if --escape is set
Repetition Options:
-r, --repetitions
Detects repeated non-overlapping substrings and converts them to {min,max} quantifier
notation
--min-repetitions
Specifies the minimum quantity of substring repetitions to be converted if --repetitions
is set [default: 1]
--min-substring-length
Specifies the minimum length a repeated substring must have in order to be converted if
--repetitions is set [default: 1]
Anchor Options:
--no-start-anchor Removes the caret anchor `^` from the resulting regular expression
--no-end-anchor Removes the dollar sign anchor `$` from the resulting regular expression
--no-anchors Removes the caret and dollar sign anchors from the resulting regular
expression
Display Options:
-x, --verbose Produces a nicer-looking regular expression in verbose mode
-c, --colorize Provides syntax highlighting for the resulting regular expression
Miscellaneous Options:
-i, --ignore-case Performs case-insensitive matching, letters match both upper and lower case
-g, --capture-groups Replaces non-capturing groups with capturing ones
-h, --help Prints help information
-v, --version Prints version information
Les cas de test sont transmis soit à partir d'une collection via RegExpBuilder::from()
, soit à partir d'un fichier via RegExpBuilder::from_file()
. S'il est lu à partir d'un fichier, chaque scénario de test doit se trouver sur une ligne distincte. Les lignes peuvent se terminer soit par une nouvelle ligne n
, soit par un retour chariot avec un saut de ligne rn
.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "a" , "aa" , "aaa" ] ) . build ( ) ;
assert_eq ! ( regexp , "^a(?:aa?)?$" ) ;
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "a" , "aa" , "123" ] )
. with_conversion_of_digits ( )
. with_conversion_of_words ( )
. build ( ) ;
assert_eq ! ( regexp , "^( \ d \ d \ d| \ w(?: \ w)?)$" ) ;
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "aa" , "bcbc" , "defdefdef" ] )
. with_conversion_of_repetitions ( )
. build ( ) ;
assert_eq ! ( regexp , "^(?:a{2}|(?:bc){2}|(?:def){3})$" ) ;
Par défaut, grex convertit ainsi chaque sous-chaîne qui comporte au moins un seul caractère et qui est ensuite répétée au moins une fois. Vous pouvez personnaliser ces deux paramètres si vous le souhaitez.
Dans l'exemple suivant, le scénario de test aa
n'est pas converti en a{2}
car la sous-chaîne répétée a
a une longueur de 1, mais la longueur minimale de la sous-chaîne a été définie sur 2.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "aa" , "bcbc" , "defdefdef" ] )
. with_conversion_of_repetitions ( )
. with_minimum_substring_length ( 2 )
. build ( ) ;
assert_eq ! ( regexp , "^(?:aa|(?:bc){2}|(?:def){3})$" ) ;
En définissant un nombre minimum de 2 répétitions dans l'exemple suivant, seul le scénario de test defdefdef
sera converti car c'est le seul qui est répété deux fois.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "aa" , "bcbc" , "defdefdef" ] )
. with_conversion_of_repetitions ( )
. with_minimum_repetitions ( 2 )
. build ( ) ;
assert_eq ! ( regexp , "^(?:bcbc|aa|(?:def){3})$" ) ;
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "You smell like ?." ] )
. with_escaping_of_non_ascii_chars ( false )
. build ( ) ;
assert_eq ! ( regexp , "^You smell like \ u{1f4a9} \ .$" ) ;
Les anciennes versions de JavaScript ne prennent pas en charge les séquences d'échappement Unicode pour les plans de code astral (plage U+010000
à U+10FFFF
). Afin de prendre en charge ces symboles dans les expressions régulières JavaScript, la conversion en paires de substitution est nécessaire. Plus d’informations à ce sujet peuvent être trouvées ici.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "You smell like ?." ] )
. with_escaped_non_ascii_chars ( true )
. build ( ) ;
assert_eq ! ( regexp , "^You smell like \ u{d83d} \ u{dca9} \ .$" ) ;
Les expressions régulières générées par grex sont sensibles à la casse par défaut. La correspondance insensible à la casse peut être activée comme suit :
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "big" , "BIGGER" ] )
. with_case_insensitive_matching ( )
. build ( ) ;
assert_eq ! ( regexp , "(?i)^big(?:ger)?$" ) ;
Les groupes sans capture sont utilisés par défaut. En étendant l'exemple précédent, vous pouvez plutôt passer à la capture de groupes.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "big" , "BIGGER" ] )
. with_case_insensitive_matching ( )
. with_capturing_groups ( )
. build ( ) ;
assert_eq ! ( regexp , "(?i)^big(ger)?$" ) ;
Si vous trouvez l'expression régulière générée difficile à lire, vous pouvez activer le mode détaillé. L’expression est ensuite mise sur plusieurs lignes et mise en retrait pour la rendre plus agréable à l’œil.
use grex :: RegExpBuilder ;
use indoc :: indoc ;
let regexp = RegExpBuilder :: from ( & [ "a" , "b" , "bcd" ] )
. with_verbose_mode ( )
. build ( ) ;
assert_eq ! ( regexp , indoc! (
r#"
(?x)
^
(?:
b
(?:
cd
)?
|
a
)
$"#
) ) ;
Par défaut, les ancres ^
et $
sont placées autour de chaque expression régulière générée afin de garantir qu'elle correspond uniquement aux cas de test donnés en entrée. Assez souvent, cependant, on souhaite utiliser le modèle généré dans le cadre d’un modèle plus vaste. A cet effet, les ancrages peuvent être désactivés, soit séparément, soit les deux.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "a" , "aa" , "aaa" ] )
. without_anchors ( )
. build ( ) ;
assert_eq ! ( regexp , "a(?:aa?)?" ) ;
Les exemples suivants montrent les différentes fonctionnalités de syntaxe regex prises en charge :
$ grex a b c
^[a-c]$
$ grex a c d e f
^[ac-f]$
$ grex a b x de
^( ? :de | [abx])$
$ grex abc bc
^a ? bc$
$ grex a b bc
^( ? :bc ? | a)$
$ grex [a-z]
^ [ a - z ] $
$ grex -r b ba baa baaa
^b( ? :a{1,3}) ? $
$ grex -r b ba baa baaaa
^b( ? :a{1,2} | a{4}) ? $
$ grex y̆ a z
^( ? :y̆ | [az])$
Note:
Grapheme y̆ consists of two Unicode symbols:
U+0079 (Latin Small Letter Y)
U+0306 (Combining Breve)
$ grex " I ♥ cake " " I ♥ cookies "
^I ♥ c( ? :ookies | ake)$
Note:
Input containing blank space must be
surrounded by quotation marks.
La chaîne "I ♥♥♥ 36 and ٣ and ??."
sert d'entrée pour les exemples suivants en utilisant la notation de ligne de commande :
$ grex < INPUT >
^I ♥♥♥ 36 and ٣ and ?? . $
$ grex -e < INPUT >
^I u {2665} u {2665} u {2665} 36 and u {663} and u {1f4a9} u {1f4a9} . $
$ grex -e --with-surrogates < INPUT >
^I u {2665} u {2665} u {2665} 36 and u {663} and u {d83d} u {dca9} u {d83d} u {dca9} . $
$ grex -d < INPUT >
^I ♥♥♥ dd and d and ?? . $
$ grex -s < INPUT >
^I s ♥♥♥ s 36 s and s ٣ s and s ?? . $
$ grex -w < INPUT >
^ w ♥♥♥ ww www w www ?? . $
$ grex -D < INPUT >
^ DDDDDD 36 DDDDD ٣ DDDDDDDD $
$ grex -S < INPUT >
^ S SSS SS SSS S SSS SSS $
$ grex -dsw < INPUT >
^ ws ♥♥♥ sddswwwsdswwws ?? . $
$ grex -dswW < INPUT >
^ wsWWWsddswwwsdswwwsWWW $
$ grex -r < INPUT >
^I ♥{3} 36 and ٣ and ?{2} . $
$ grex -er < INPUT >
^I u {2665}{3} 36 and u {663} and u {1f4a9}{2} . $
$ grex -er --with-surrogates < INPUT >
^I u {2665}{3} 36 and u {663} and ( ? : u {d83d} u {dca9}){2} . $
$ grex -dgr < INPUT >
^I ♥{3} d ( d and ){2}?{2} . $
$ grex -rs < INPUT >
^I s ♥{3} s 36 s and s ٣ s and s ?{2} . $
$ grex -rw < INPUT >
^ w ♥{3} w ( ? : w w {3} ){2}?{2} . $
$ grex -Dr < INPUT >
^ D {6}36 D {5}٣ D {8}$
$ grex -rS < INPUT >
^ S S ( ? : S {2} ){2} S {3} S S {3} S {3}$
$ grex -rW < INPUT >
^I W {5}36 W and W ٣ W and W {4}$
$ grex -drsw < INPUT >
^ ws ♥{3} sd ( ? : dsw {3} s ){2}?{2} . $
$ grex -drswW < INPUT >
^ wsW {3} sd ( ? : dsw {3} s ){2} W {3}$
Afin de créer le code source vous-même, vous avez besoin de la chaîne d'outils Rust stable installée sur votre machine afin que cargo , le gestionnaire de packages Rust soit disponible. Attention : Rust >= 1.70.0 est requis pour construire la CLI. Pour la partie bibliothèque, Rust < 1.70.0 est suffisant.
git clone https://github.com/pemistahl/grex.git
cd grex
cargo build
Le code source est accompagné d'une suite de tests complète composée de tests unitaires, de tests d'intégration et de tests de propriétés. Pour les exécuter, dites simplement :
cargo test
Des benchmarks mesurant les performances de plusieurs paramètres peuvent être exécutés avec :
cargo bench
Avec l'aide de PyO3 et Maturin, la bibliothèque a été compilée dans un module d'extension Python afin qu'elle puisse également être utilisée dans n'importe quel logiciel Python. Il est disponible dans le Python Package Index et peut être installé avec :
pip install grex
Pour créer vous-même le module d'extension Python, créez un environnement virtuel et installez Maturin.
python -m venv /path/to/virtual/environment
source /path/to/virtual/environment/bin/activate
pip install maturin
maturin build
La bibliothèque Python contient une seule classe nommée RegExpBuilder
qui peut être importée comme suit :
from grex import RegExpBuilder
Cette bibliothèque peut être compilée en WebAssembly (WASM), ce qui permet d'utiliser grex dans n'importe quel projet basé sur JavaScript, que ce soit dans le navigateur ou dans le back-end exécuté sur Node.js.
Le moyen le plus simple de compiler est d'utiliser wasm-pack
. Après l'installation, vous pouvez par exemple construire la bibliothèque avec la cible web afin qu'elle puisse être directement utilisée dans le navigateur :
wasm-pack build --target web
Cela crée un répertoire nommé pkg
au niveau supérieur de ce référentiel, contenant les fichiers wasm compilés et les liaisons JavaScript et TypeScript. Dans un fichier HTML, vous pouvez alors appeler grex comme suit, par exemple :
< script type =" module " >
import init , { RegExpBuilder } from "./pkg/grex.js" ;
init ( ) . then ( _ => {
alert ( RegExpBuilder . from ( [ "hello" , "world" ] ) . build ( ) ) ;
} ) ;
script >
Des tests d'intégration sont également disponibles pour Node.js et pour les navigateurs Chrome, Firefox et Safari. Pour les exécuter, dites simplement :
wasm-pack test --node --headless --chrome --firefox --safari
Si les tests ne démarrent pas dans Safari, vous devez d'abord activer le pilote Web de Safari en exécutant :
sudo safaridriver --enable
La sortie de wasm-pack
sera hébergée dans un référentiel séparé qui permettra d'ajouter d'autres configurations, tests et documentations liés à JavaScript. grex sera ensuite également ajouté au registre npm, permettant un téléchargement et une installation faciles dans chaque projet JavaScript ou TypeScript.
Il existe un site Web de démonstration disponible sur lequel vous pouvez essayer grex.
Un automate fini déterministe (DFA) est créé à partir des chaînes d'entrée.
Le nombre d'états et de transitions entre les états dans le DFA est réduit en appliquant l'algorithme de minimisation DFA de Hopcroft.
Le DFA minimisé est exprimé sous la forme d'un système d'équations linéaires qui sont résolues avec la méthode algébrique de Brzozowski, aboutissant à l'expression régulière finale.
Jetez un œil aux numéros prévus.
Si vous souhaitez contribuer quelque chose à grex , je vous encourage à le faire. Avez-vous des idées de fonctionnalités intéressantes ? Ou avez-vous trouvé des bugs jusqu'à présent ? N'hésitez pas à ouvrir un ticket ou à envoyer une pull request. C'est très apprécié. :-)