PHP 재미: 8.5의 regex 빌더
Source: Dev.to
왜?
주된 이유는 이것이 텍스트를 생성하는 빌더이므로 객체를 인스턴스화할 필요가 없기 때문입니다.
두 번째 이유는 내장 PHP 정규식 함수를 객체 메서드로 감싸는 대신 직접 사용해야 한다는 점입니다:
$match = preg_match($pattern, 'test'); // instead of duplicates.IsMatch('test')
어떻게 작동할까?
전체 라이브러리를 만들지는 않을 것이며, C# 라이브러리의 몇 가지 가능성을 파이프 연산자 형태로 강조하겠습니다.
시작은 빈 문자열, 구분자가 포함된 문자열, 혹은 구분자 함수가 될 수 있습니다.
$pattern = '' |> anyCharacter(...); // regex: .*
// or
$pattern = '/' |> anyCharacter(...);
// or
$pattern = delimiter() |> anyCharacter(...);
라이브러리는 클래스 상수(예: Pattern.With.LowercaseLetter)를 사용해 알려진 문자 패턴을 추가합니다. PHP에서는 이를 백드 enum으로 구현할 수 있으며, anyCharacter 함수는 인자를 받는 any 함수로 바뀔 수 있습니다.
enum CharacterPattern: string
{
case Any = '.';
case LowercaseLetter = '[a-z]';
case Word = '\w';
}
function any(string $pattern, CharacterPattern|string $add = CharacterPattern::Any): string
{
$addPattern = $add instanceof CharacterPattern ? $add->value : $add;
return "$pattern$addPattern*";
}
// examples
$pattern = '' |> fn($p) => any($p);
$pattern = '' |> fn($p) => any($p, CharacterPattern::LowercaseLetter);
$pattern = '' |> fn($p) => any($p, '[sunday|monday]');
마지막 예제에서는 라이브러리가 literal 메서드가 필요했지만, 타입 힌트만으로 충분합니다.
양화 패턴 함수를 완성하기 위해 exact와 atLeast 함수를 추가할 수 있습니다.
양수 전방 탐색
PositiveLookahead 메서드는 중첩된 함수 호출을 만들 수 있습니다. 이를 두 개의 함수로 나누면 빌더가 평평하게 유지됩니다.
function positiveLookaheadStart(string $pattern, string $times = ''): string
{
return "$pattern(?=$times";
}
function positiveLookaheadEnd(string $pattern): string
{
return "$pattern)";
}
// example
$pattern = ''
|> fn($p) => positiveLookaheadStart($p, '.*')
|> fn($p) => any($p, '[sunday|monday]')
|> fn($p) => positiveLookaheadEnd($p);
명명된 그룹 및 역참조
NamedGroup 같은 메서드는 캡처되지 않는 그룹도 처리하는 group 함수로 분리할 수 있습니다. 역참조는 단순히 \1 또는 \k 입니다.
function backReference(string $pattern, int|string $add): string
{
$reference = is_string($add) ? "k" : $add;
return "$pattern\\$reference";
}
결론
파이프 연산자를 사용하면 각 함수가 부작용 없이 한 가지 일을 수행하므로 코드 양이 줄어듭니다. 이는 정규식 빌딩이 언어 수준에서 이루어지기 때문에 테스트해야 할 엣지 케이스도 감소한다는 의미입니다.
작은 단점은 일반적인 함수 이름이 유창한 API보다 직관적이지 않을 수 있다는 점입니다. 이를 완화하려면 직접 설명적인 함수를 추가해 라이브러리를 쉽게 확장할 수 있습니다.
다음에 빌더 패턴을 고려할 때 파이프 연산자가 더 적합한지 스스로에게 물어보세요.
PS: 프로덕션 환경에서는 정규식 빌더를 사용하지 마세요; 대신 미리 준비된 캐시에서 생성된 패턴을 사용하십시오.