PHP 趣味:regex builder 在 8.5 中

发布: (2026年1月9日 GMT+8 06:06)
4 min read
原文: Dev.to

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 中这可以是带值的枚举,而 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 方法;类型提示已经足够。

为了完成量化模式函数,我们可以添加 exactatLeast 函数。

正向前瞻

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: 不要在生产环境中使用正则构建器;请使用预热缓存中的生成模式。

Back to Blog

相关文章

阅读更多 »

Dev.to API 介绍

入门 - 登录你的 dev.to 账户。 - 前往 设置 → 账户。 - 向下滚动到 DEV API Keys 部分。 - 生成一个新密钥并将其复制到某处。

我的 NewbieDevDiary #0000

已清理的 Markdown markdown !Forem Logo https://media2.dev.to/dynamic/image/width=65,height=,fit=scale-down,gravity=auto,format=auto/https%3A%2F%2Fdev-to-upload...