grex 는 정규식을 생성하는 복잡하고 지루한 작업을 단순화하기 위한 라이브러리이자 명령줄 유틸리티입니다. 이는 사용자가 제공한 테스트 사례에서 단일 정규식을 자동으로 생성하여 수행됩니다. 결과 표현식은 생성된 테스트 사례와 일치하는 것이 보장됩니다.
이 프로젝트는 Devon Govett가 작성한 JavaScript 도구 regexgen 의 Rust 포트로 시작되었습니다. 더 많은 유용한 기능을 추가할 수 있었지만 몇 년 전에 개발이 중단된 것으로 보입니다. Rust가 명령줄 도구에 있어서 정말 빛을 발하기 때문에 이제 이러한 새로운 기능을 grex 에 추가할 계획입니다. grex는 regexgen이 제공하는 모든 기능 등을 제공합니다.
이 프로젝트의 철학은 기본적으로 주어진 입력에만 정확히 일치하고 그 외에는 아무것도 일치하지 않는 가장 구체적인 정규식을 생성하는 것입니다. 명령줄 플래그(CLI 도구) 또는 전처리 방법(라이브러리)을 사용하면 보다 일반화된 표현식을 생성할 수 있습니다.
생성된 표현식은 Rust의 정규 표현식 상자에 있는 정규 표현식 파서와도 호환되는 Perl 호환 정규 표현식입니다. 다른 프로그래밍 언어의 다른 정규식 파서 또는 해당 라이브러리는 지금까지 테스트되지 않았지만 대부분 호환될 것입니다.
물론이죠, 그렇습니다! 표준 설정을 사용하여 grex는 입력으로 제공된 테스트 사례만 일치하고 다른 것은 일치하지 않는 정규식을 생성합니다. 이는 속성 테스트를 통해 검증되었습니다. 그러나 w
와 같은 단축 문자 클래스로의 변환이 활성화되면 결과 정규식은 훨씬 더 넓은 범위의 테스트 사례와 일치합니다. 비즈니스 도메인에 대한 올바른 정규식을 찾으려면 이 변환의 결과에 대한 지식이 필수적입니다.
grex는 주어진 테스트 케이스에 대해 가능한 가장 짧은 정규식을 찾으려고 시도하는 알고리즘을 사용합니다. 하지만 결과 표현식이 필요한 것보다 더 길거나 더 복잡한 경우가 많습니다. 이러한 경우에는 보다 간결하고 우아한 정규식을 직접 생성할 수 있습니다. 또한 모든 정규식 엔진에는 서로 다른 최적화 기능이 내장되어 있습니다. grex는 이에 대해 아무것도 모르므로 특정 엔진에 대한 정규식을 최적화할 수 없습니다.
그럼 정규식 작성법을 배워보세요! 현재 grex 의 가장 좋은 사용 사례는 추가 최적화가 가능한 경우 직접 검사해야 하는 초기의 올바른 정규식을 찾는 것입니다.
{min,max}
수량자 표기법으로 변환|
사용하여 교대 연산자?
수량자^
및 $
위의 플랫폼에 대한 자체 포함 실행 파일을 다운로드하여 원하는 위치에 배치할 수 있습니다. 또는 사전 컴파일된 64비트 바이너리를 패키지 관리자 Scoop(Windows용), Homebrew(macOS 및 Linux용), MacPorts(macOS용) 및 Huber(macOS, Linux 및 Windows용)에서 사용할 수 있습니다. Raúl Piracés는 Chocolatey Windows 패키지에 기여했습니다.
grex는 공식 Rust 패키지 레지스트리인 crates.io에서도 호스팅됩니다. Rust 개발자이고 이미 Rust 툴체인이 설치되어 있는 경우 Rust 패키지 관리자인 Cargo 를 사용하여 소스에서 컴파일하여 설치할 수 있습니다. 따라서 설치 옵션 요약은 다음과 같습니다.
( brew | cargo | choco | huber | port | scoop ) install grex
grex를 라이브러리로 사용하려면 간단히 Cargo.toml
파일에 종속성으로 추가하면 됩니다.
[ dependencies ]
grex = { version = " 1.4.5 " , default-features = false }
종속성 박수 는 명령줄 도구에만 필요합니다. 기본 기능을 비활성화하면 라이브러리에 대한 박수 다운로드 및 컴파일이 방지됩니다.
사용 가능한 설정에 대한 자세한 설명은 라이브러리 섹션에서 제공됩니다. 모든 설정은 서로 자유롭게 결합될 수 있습니다.
테스트 사례는 직접( grex abc
) 또는 파일( grex -f test_cases.txt
)에서 전달됩니다. grex는 Unix 파이프라인에서도 입력을 받을 수 있습니다(예: cat test_cases.txt | grex -
.
다음 표에는 사용 가능한 모든 플래그와 옵션이 나와 있습니다.
$ 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
테스트 케이스는 RegExpBuilder::from()
통해 컬렉션에서 전달되거나 RegExpBuilder::from_file()
통해 파일에서 전달됩니다. 파일에서 읽는 경우 각 테스트 사례는 별도의 줄에 있어야 합니다. 줄은 개행 문자 n
또는 줄 바꿈 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})$" ) ;
기본적으로 grex는 각 하위 문자열을 이러한 방식으로 변환합니다. 이 방식은 최소 한 문자 길이이고 이후에 최소 한 번 반복됩니다. 원하는 경우 이 두 매개변수를 사용자 정의할 수 있습니다.
다음 예에서는 반복되는 하위 문자열 a
의 길이가 1이지만 최소 하위 문자열 길이가 2로 설정되었기 때문에 테스트 사례 aa
a{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})$" ) ;
다음 예에서 최소 2회 반복 횟수를 설정하면 defdefdef
테스트 케이스만 두 번 반복되는 유일한 테스트 케이스이므로 변환됩니다.
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} \ .$" ) ;
이전 버전의 JavaScript는 아스트랄 코드 평면(범위 U+010000
~ U+10FFFF
)에 대한 유니코드 이스케이프 시퀀스를 지원하지 않습니다. JavaScript 정규식에서 이러한 기호를 지원하려면 서로게이트 쌍으로 변환해야 합니다. 해당 문제에 대한 자세한 내용은 여기에서 확인할 수 있습니다.
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} \ .$" ) ;
grex가 생성하는 정규식은 기본적으로 대소문자를 구분합니다. 대소문자를 구분하지 않는 일치는 다음과 같이 활성화할 수 있습니다.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "big" , "BIGGER" ] )
. with_case_insensitive_matching ( )
. build ( ) ;
assert_eq ! ( regexp , "(?i)^big(?:ger)?$" ) ;
비캡처 그룹은 기본적으로 사용됩니다. 이전 예제를 확장하면 대신 캡처 그룹으로 전환할 수 있습니다.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "big" , "BIGGER" ] )
. with_case_insensitive_matching ( )
. with_capturing_groups ( )
. build ( ) ;
assert_eq ! ( regexp , "(?i)^big(ger)?$" ) ;
생성된 정규식을 읽기 어려운 경우 자세한 정보 표시 모드를 활성화할 수 있습니다. 그런 다음 표현식을 여러 줄에 걸쳐 들여쓰기하여 눈에 더 보기 좋게 만듭니다.
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
)
$"#
) ) ;
기본적으로 ^
및 $
앵커는 입력으로 제공된 테스트 사례에만 일치하는지 확인하기 위해 생성된 모든 정규식 주위에 배치됩니다. 그러나 생성된 패턴을 더 큰 패턴의 일부로 사용하는 것이 바람직한 경우도 많습니다. 이를 위해 앵커를 개별적으로 또는 둘 다 비활성화할 수 있습니다.
use grex :: RegExpBuilder ;
let regexp = RegExpBuilder :: from ( & [ "a" , "aa" , "aaa" ] )
. without_anchors ( )
. build ( ) ;
assert_eq ! ( regexp , "a(?:aa?)?" ) ;
다음 예에서는 지원되는 다양한 정규식 구문 기능을 보여줍니다.
$ 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.
문자열 "I ♥♥♥ 36 and ٣ and ??."
명령줄 표기법을 사용하여 다음 예에 대한 입력으로 사용됩니다.
$ 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}$
소스 코드를 직접 빌드하려면, Rust 패키지 관리자인 화물을 사용할 수 있도록 컴퓨터에 안정적인 Rust 툴체인이 설치되어 있어야 합니다. 참고 : CLI를 빌드하려면 Rust >= 1.70.0이 필요합니다. 라이브러리 부분의 경우 Rust < 1.70.0이면 충분합니다.
git clone https://github.com/pemistahl/grex.git
cd grex
cargo build
소스 코드에는 단위 테스트, 통합 테스트 및 속성 테스트로 구성된 광범위한 테스트 모음이 함께 제공됩니다. 실행하려면 다음과 같이 간단히 말하세요.
cargo test
여러 설정의 성능을 측정하는 벤치마크는 다음을 사용하여 실행할 수 있습니다.
cargo bench
PyO3 및 Maturin의 도움으로 라이브러리는 Python 확장 모듈로 컴파일되어 모든 Python 소프트웨어 내에서도 사용할 수 있습니다. Python 패키지 색인에서 사용할 수 있으며 다음을 사용하여 설치할 수 있습니다.
pip install grex
Python 확장 모듈을 직접 빌드하려면 가상 환경을 만들고 Maturin을 설치하세요.
python -m venv /path/to/virtual/environment
source /path/to/virtual/environment/bin/activate
pip install maturin
maturin build
Python 라이브러리에는 다음과 같이 가져올 수 있는 RegExpBuilder
라는 단일 클래스가 포함되어 있습니다.
from grex import RegExpBuilder
이 라이브러리는 브라우저나 Node.js에서 실행되는 백엔드 등 모든 JavaScript 기반 프로젝트에서 grex를 사용할 수 있는 WebAssembly(WASM)로 컴파일될 수 있습니다.
컴파일하는 가장 쉬운 방법은 wasm-pack
사용하는 것입니다. 예를 들어, 설치 후 브라우저에서 직접 사용할 수 있도록 웹 대상으로 라이브러리를 빌드할 수 있습니다.
wasm-pack build --target web
그러면 컴파일된 wasm 파일과 JavaScript 및 TypeScript 바인딩이 포함된 pkg
라는 디렉터리가 이 저장소의 최상위 수준에 생성됩니다. HTML 파일에서 다음과 같이 grex를 호출할 수 있습니다.
< script type =" module " >
import init , { RegExpBuilder } from "./pkg/grex.js" ;
init ( ) . then ( _ => {
alert ( RegExpBuilder . from ( [ "hello" , "world" ] ) . build ( ) ) ;
} ) ;
script >
Node.js와 Chrome, Firefox, Safari 브라우저 모두에 사용할 수 있는 몇 가지 통합 테스트도 있습니다. 실행하려면 간단히 다음과 같이 말하세요.
wasm-pack test --node --headless --chrome --firefox --safari
Safari에서 테스트가 시작되지 않으면 먼저 다음을 실행하여 Safari의 웹 드라이버를 활성화해야 합니다.
sudo safaridriver --enable
wasm-pack
의 출력은 JavaScript 관련 구성, 테스트 및 문서를 추가할 수 있는 별도의 저장소에 호스팅됩니다. 그러면 grex가 npm 레지스트리에도 추가되어 모든 JavaScript 또는 TypeScript 프로젝트 내에서 쉽게 다운로드하고 설치할 수 있습니다.
grex를 시험해 볼 수 있는 데모 웹사이트가 있습니다.
결정론적 유한 자동 장치(DFA)는 입력 문자열에서 생성됩니다.
Hopcroft의 DFA 최소화 알고리즘을 적용하면 DFA의 상태 수와 상태 간 전환이 줄어듭니다.
최소화된 DFA는 Brzozowski의 대수적 방법으로 풀린 선형 방정식 시스템으로 표현되어 최종 정규 표현식이 됩니다.
예정된 이슈를 살펴보세요.
grex 에 무언가 기여하고 싶다면 그렇게 하시기를 권장합니다. 멋진 기능에 대한 아이디어가 있나요? 아니면 지금까지 버그를 발견하셨나요? 자유롭게 이슈를 열거나 풀 요청을 보내주세요. 정말 감사합니다. :-)