grex ist sowohl eine Bibliothek als auch ein Befehlszeilendienstprogramm, das die oft komplizierte und mühsame Aufgabe der Erstellung regulärer Ausdrücke vereinfachen soll. Dies geschieht durch die automatische Generierung eines einzelnen regulären Ausdrucks aus vom Benutzer bereitgestellten Testfällen. Der resultierende Ausdruck stimmt garantiert mit den Testfällen überein, aus denen er generiert wurde.
Dieses Projekt wurde als Rust-Portierung des von Devon Govett geschriebenen JavaScript-Tools regexgen gestartet. Obwohl viele weitere nützliche Funktionen hinzugefügt werden könnten, wurde die Entwicklung offenbar bereits vor einigen Jahren eingestellt. Der Plan besteht nun darin, diese neuen Funktionen zu grex hinzuzufügen, da Rust wirklich glänzt, wenn es um Befehlszeilentools geht. grex bietet alle Funktionen, die regexgen bietet, und noch mehr.
Die Philosophie dieses Projekts besteht darin, standardmäßig einen möglichst spezifischen regulären Ausdruck zu generieren, der nur der gegebenen Eingabe und nichts anderem genau entspricht. Mithilfe von Befehlszeilenflags (im CLI-Tool) oder Vorverarbeitungsmethoden (in der Bibliothek) können allgemeinere Ausdrücke erstellt werden.
Die erzeugten Ausdrücke sind Perl-kompatible reguläre Ausdrücke, die auch mit dem Parser für reguläre Ausdrücke in Rusts Regex- Kiste kompatibel sind. Andere Parser für reguläre Ausdrücke oder entsprechende Bibliotheken aus anderen Programmiersprachen wurden bisher nicht getestet, sollten aber ebenfalls größtenteils kompatibel sein.
Auf jeden Fall, ja! Mit den Standardeinstellungen erzeugt grex einen regulären Ausdruck, der garantiert nur mit den als Eingabe angegebenen Testfällen übereinstimmt und mit nichts anderem. Dies wurde durch Eigenschaftstests bestätigt. Wenn jedoch die Konvertierung in Kurzzeichenklassen wie w
aktiviert ist, entspricht der resultierende reguläre Ausdruck einem viel größeren Umfang an Testfällen. Um einen korrekten regulären Ausdruck für Ihre Unternehmensdomäne zu finden, ist es wichtig, die Konsequenzen dieser Konvertierung zu kennen.
grex verwendet einen Algorithmus, der versucht, den kürzestmöglichen regulären Ausdruck für die gegebenen Testfälle zu finden. Sehr oft ist der resultierende Ausdruck jedoch immer noch länger oder komplexer als nötig. In solchen Fällen kann eine kompaktere oder elegantere Regex nur von Hand erstellt werden. Außerdem verfügt jede Engine für reguläre Ausdrücke über unterschiedliche integrierte Optimierungen. grex weiß nichts darüber und kann daher seine regulären Ausdrücke nicht für eine bestimmte Engine optimieren.
Lernen Sie also bitte, wie man reguläre Ausdrücke schreibt! Der derzeit beste Anwendungsfall für Grex besteht darin, einen anfänglichen korrekten regulären Ausdruck zu finden, der manuell überprüft werden sollte, ob weitere Optimierungen möglich sind.
{min,max}
|
Operator?
Quantor^
und $
Sie können oben die eigenständige ausführbare Datei für Ihre Plattform herunterladen und an einem Ort Ihrer Wahl ablegen. Alternativ sind vorkompilierte 64-Bit-Binärdateien in den Paketmanagern Scoop (für Windows), Homebrew (für macOS und Linux), MacPorts (für macOS) und Huber (für macOS, Linux und Windows) verfügbar. Raúl Piracés hat ein Chocolatey Windows-Paket beigesteuert.
grex wird auch auf crates.io gehostet, der offiziellen Rust-Paketregistrierung. Wenn Sie ein Rust-Entwickler sind und die Rust-Toolchain bereits installiert haben, können Sie die Installation durch Kompilieren aus dem Quellcode mit Cargo , dem Rust-Paketmanager, durchführen. Die Zusammenfassung Ihrer Installationsoptionen lautet also:
( brew | cargo | choco | huber | port | scoop ) install grex
Um grex als Bibliothek zu verwenden, fügen Sie es einfach als Abhängigkeit zu Ihrer Cargo.toml
Datei hinzu:
[ dependencies ]
grex = { version = " 1.4.5 " , default-features = false }
Das Abhängigkeitsklatschen wird nur für das Befehlszeilentool benötigt. Durch Deaktivieren der Standardfunktionen wird das Herunterladen und Kompilieren von Clap für die Bibliothek verhindert.
Detaillierte Erläuterungen zu den verfügbaren Einstellungen finden Sie im Bibliotheksbereich. Alle Einstellungen sind frei miteinander kombinierbar.
Testfälle werden entweder direkt ( grex abc
) oder aus einer Datei ( grex -f test_cases.txt
) übergeben. grex kann seine Eingaben auch von Unix-Pipelines empfangen, z. B. cat test_cases.txt | grex -
.
Die folgende Tabelle zeigt alle verfügbaren Flags und Optionen:
$ 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
Testfälle werden entweder aus einer Sammlung über RegExpBuilder::from()
oder aus einer Datei über RegExpBuilder::from_file()
übergeben. Beim Lesen aus einer Datei muss jeder Testfall in einer separaten Zeile stehen. Zeilen können entweder mit einem Zeilenumbruch n
oder einem Wagenrücklauf mit einem Zeilenvorschub rn
beendet werden.
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})$" ) ;
Standardmäßig konvertiert grex auf diese Weise jeden Teilstring, der mindestens ein einzelnes Zeichen lang ist und anschließend mindestens einmal wiederholt wird. Sie können diese beiden Parameter bei Bedarf anpassen.
Im folgenden Beispiel wird der Testfall aa
nicht in a{2}
konvertiert, da der wiederholte Teilstring a
eine Länge von 1 hat, die minimale Teilstringlänge jedoch auf 2 festgelegt wurde.
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})$" ) ;
Wenn Sie im nächsten Beispiel eine Mindestanzahl von 2 Wiederholungen festlegen, wird nur der Testfall defdefdef
konvertiert, da er der einzige ist, der zweimal wiederholt wird.
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} \ .$" ) ;
Alte Versionen von JavaScript unterstützen keine Unicode-Escape-Sequenzen für die Astralebeneben (Bereich U+010000
bis U+10FFFF
). Um diese Symbole in regulären JavaScript-Ausdrücken zu unterstützen, ist die Konvertierung in Ersatzzeichenpaare erforderlich. Weitere Informationen zu diesem Thema finden Sie hier.
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} \ .$" ) ;
Bei den von grex generierten regulären Ausdrücken wird standardmäßig die Groß-/Kleinschreibung beachtet. Der Abgleich ohne Berücksichtigung der Groß-/Kleinschreibung kann wie folgt aktiviert werden:
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "big" , "BIGGER" ] )
. with_case_insensitive_matching ( )
. build ( ) ;
assert_eq ! ( regexp , "(?i)^big(?:ger)?$" ) ;
Standardmäßig werden nicht erfassende Gruppen verwendet. Als Erweiterung des vorherigen Beispiels können Sie stattdessen zur Erfassung von Gruppen wechseln.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "big" , "BIGGER" ] )
. with_case_insensitive_matching ( )
. with_capturing_groups ( )
. build ( ) ;
assert_eq ! ( regexp , "(?i)^big(ger)?$" ) ;
Wenn Sie den generierten regulären Ausdruck schwer lesbar finden, können Sie den ausführlichen Modus aktivieren. Der Ausdruck wird dann in mehrere Zeilen geschrieben und eingerückt, um ihn für das Auge angenehmer zu machen.
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
)
$"#
) ) ;
Standardmäßig werden die Anker ^
und $
um jeden generierten regulären Ausdruck gelegt, um sicherzustellen, dass er nur mit den als Eingabe angegebenen Testfällen übereinstimmt. Oftmals besteht jedoch der Wunsch, das erzeugte Muster als Teil eines größeren Musters zu verwenden. Zu diesem Zweck können die Anker einzeln oder beide deaktiviert werden.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "a" , "aa" , "aaa" ] )
. without_anchors ( )
. build ( ) ;
assert_eq ! ( regexp , "a(?:aa?)?" ) ;
Die folgenden Beispiele zeigen die verschiedenen unterstützten Regex-Syntaxfunktionen:
$ 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.
Die Zeichenfolge "I ♥♥♥ 36 and ٣ and ??."
dient als Eingabe für die folgenden Beispiele unter Verwendung der Befehlszeilennotation:
$ 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}$
Um den Quellcode selbst zu erstellen, muss die stabile Rust-Toolchain auf Ihrem Rechner installiert sein, damit Cargo , der Rust-Paketmanager, verfügbar ist. Bitte beachten Sie : Zum Erstellen der CLI ist Rust >= 1.70.0 erforderlich. Für den Bibliotheksteil ist Rust < 1.70.0 ausreichend.
git clone https://github.com/pemistahl/grex.git
cd grex
cargo build
Dem Quellcode liegt eine umfangreiche Testsuite bestehend aus Unit-Tests, Integrationstests und Property-Tests bei. Um sie auszuführen, sagen Sie einfach:
cargo test
Benchmarks zur Messung der Leistung verschiedener Einstellungen können ausgeführt werden mit:
cargo bench
Mit Hilfe von PyO3 und Maturin wurde die Bibliothek zu einem Python-Erweiterungsmodul kompiliert, sodass sie auch in jeder Python-Software verwendet werden kann. Es ist im Python Package Index verfügbar und kann installiert werden mit:
pip install grex
Um das Python-Erweiterungsmodul selbst zu erstellen, erstellen Sie eine virtuelle Umgebung und installieren Sie Maturin.
python -m venv /path/to/virtual/environment
source /path/to/virtual/environment/bin/activate
pip install maturin
maturin build
Die Python-Bibliothek enthält eine einzelne Klasse namens RegExpBuilder
, die wie folgt importiert werden kann:
from grex import RegExpBuilder
Diese Bibliothek kann zu WebAssembly (WASM) kompiliert werden, was die Verwendung von Grex in jedem JavaScript-basierten Projekt ermöglicht, sei es im Browser oder im Back-End, das auf Node.js läuft.
Der einfachste Weg zum Kompilieren ist die Verwendung wasm-pack
. Nach der Installation können Sie beispielsweise die Bibliothek mit dem Web-Target so aufbauen, dass sie direkt im Browser genutzt werden kann:
wasm-pack build --target web
Dadurch wird auf der obersten Ebene dieses Repositorys ein Verzeichnis mit dem Namen pkg
erstellt, das die kompilierten WASM-Dateien sowie JavaScript- und TypeScript-Bindungen enthält. In einer HTML-Datei können Sie grex dann beispielsweise wie folgt aufrufen:
< script type =" module " >
import init , { RegExpBuilder } from "./pkg/grex.js" ;
init ( ) . then ( _ => {
alert ( RegExpBuilder . from ( [ "hello" , "world" ] ) . build ( ) ) ;
} ) ;
script >
Darüber hinaus stehen einige Integrationstests sowohl für Node.js als auch für die Browser Chrome, Firefox und Safari zur Verfügung. Um sie auszuführen, sagen Sie einfach:
wasm-pack test --node --headless --chrome --firefox --safari
Wenn die Tests in Safari nicht starten, müssen Sie zunächst den Webtreiber von Safari aktivieren, indem Sie Folgendes ausführen:
sudo safaridriver --enable
Die Ausgabe von wasm-pack
wird in einem separaten Repository gehostet, das das Hinzufügen weiterer JavaScript-bezogener Konfigurationen, Tests und Dokumentationen ermöglicht. grex wird dann auch zur npm-Registrierung hinzugefügt, was einen einfachen Download und eine einfache Installation in jedem JavaScript- oder TypeScript-Projekt ermöglicht.
Es gibt eine Demo-Website, auf der Sie Grex ausprobieren können.
Aus den Eingabezeichenfolgen wird ein deterministischer endlicher Automat (DFA) erstellt.
Die Anzahl der Zustände und Übergänge zwischen Zuständen im DFA wird durch die Anwendung des DFA-Minimierungsalgorithmus von Hopcroft reduziert.
Der minimierte DFA wird als System linearer Gleichungen ausgedrückt, die mit der algebraischen Methode von Brzozowski gelöst werden, was zum endgültigen regulären Ausdruck führt.
Werfen Sie einen Blick auf die geplanten Ausgaben.
Falls Sie etwas zu grex beitragen möchten, empfehle ich Ihnen, dies zu tun. Habt ihr Ideen für coole Features? Oder habt ihr bisher irgendwelche Bugs gefunden? Fühlen Sie sich frei, ein Problem zu eröffnen oder eine Pull-Anfrage zu senden. Es wird sehr geschätzt. :-)