正则表达式

最后更新: 2022-10-11 18:31:04 +0800 +0800
原文以英文撰写。您正在阅读AI翻译版本。

正则表达式并非一种单一语言。POSIX BRE、POSIX ERE 和兼容 Perl 的引擎有所重叠, 但它们的语法、匹配规则和可用功能并不相同。

POSIX BRE #

基本正则表达式是 grep 和 sed 使用的传统语法。

重要规则:

  • 使用 \( 和 \) 分组;
  • 使用 \{m,n\} 进行计数重复;
  • 除非工具增加了扩展,否则 +、?、| 和 () 都是字面字符;
  • 反向引用使用 \1、\2,依此类推。

BRE 具有可移植性,但由于许多元字符需要转义,其写法较为冗长。

POSIX ERE #

扩展正则表达式更接近现代正则表达式语法:

  • () 用于分组;
  • + 表示一次或多次;
  • ? 表示零次或一次;
  • {m,n} 计算重复次数;
  • | 表示交替。

grep -E 和 sed -E 使用这种形式。POSIX ERE 仍存在限制,因为它不支持惰性量词、前瞻或后顾。

兼容 Perl 的引擎 #

兼容 Perl 的正则表达式增加了 POSIX RE 不具备的功能:

  • *? 和 +? 等惰性量词;
  • 前瞻和后顾;
  • (?:...) 等非捕获组;
  • 许多引擎支持的命名捕获;
  • 更丰富的字符类语法。

因此,非贪婪匹配往往要求切换引擎。POSIX BRE 和 ERE 根本没有等效运算符。

匹配行为 #

POSIX 引擎采用最左最长匹配规则。即使语法看起来相似,该规则也可能产生与 Perl 风格引擎不同的结果。

当交替和重复相互重叠时,这一点很重要,因为引擎可能选择更长的匹配, 而不是第一个成功的语法分支。

锚点也取决于引擎和模式。POSIX 的 ^ 和 $ 表示字符串的开头和结尾, 针对行的行为则取决于具体工具;PCRE 风格的引擎通常提供单独的绝对字符串锚点和多行模式。 应显式匹配输入的实际边界,而不是假定命令的默认行为。

字符类并非固定的 ASCII 简写形式。[[:alpha:]] 等 POSIX 方括号字符类遵循当前区域设置, 而 \w、大小写折叠和 Unicode 属性则因兼容 Perl 的具体实现和标志而异。 对于按字节处理的自动化任务,应设置已知区域;或者有意选择引擎的 Unicode 模式。

在含义不明确的嵌套重复上,回溯引擎可能耗费指数级时间, 例如使用 (a+)+$ 匹配较长且不匹配的输入。处理不可信数据时,应限制输入大小, 避免相互重叠的分支和嵌套量词,或使用线性时间引擎。 环视和非捕获组可以改善表达式结构,但不会使不同引擎彼此兼容。

实用转换 #

同一意图经常需要不同的语法:

  • 捕获组:BRE 中为 \(...\),ERE 中为 (...);
  • 一个或多个数字:BRE 中为 \{1,\},ERE 中为 +;
  • 非贪婪通配符:POSIX RE 不支持。

需要可移植性时,应选定具体引擎,并使用满足任务需求的最小功能集。 转换应基于目标语言和匹配语义,而不是机械地添加或删除反斜杠。

评论

在 GitHub 上阅读或评论(发表评论需要登录)