关于正则表达式:RE2 (Rust) 正则表达式无法按预期工作

RE2 (Rust) regular expression doesn't work as expected

我有一个正则表达式,看起来很简单,但没有按要求行事。要解析的输入描述如下(nb: {} 不是正则表达式的一部分,只有里面的内容):

  • 0 个或多个空格的序列 {\\\\s*}
  • 破折号 {-}
  • 0 个或多个空格的序列 {\\\\s*}
  • 完整的人名(名字、中间名、姓氏;全部捕获到 f1 中)。名称不能以数字开头
    必须出现在行尾 {[A-Za-z][\\\\w\\\\s]*)}

整个结构 SPACE-SPACEf1 是可选的

只是为了解释捕获到 f1 中的内容:
对于第一个字符,我使用由 [A-Za-z] 表示的字符集。后跟 \\\\w 或空格 0 次或更多次。这被捕获到 f1.

1
(?:\\s*-\\s*(?P<f1>[A-Za-z][\\w\\s]*))?$

我希望以下序列匹配并捕获一个值到 f1:

  • "-布鲁斯"(f1=布鲁斯)
  • "——布鲁斯·狄金森"(f1=布鲁斯·狄金森)

我希望以下内容不匹配:

  • "布鲁斯"(没有前导破折号)
  • "——布鲁斯!" (在名称之后和行尾之前有一个非单词 (\\\\w) 字符

我希望以下匹配但不会将值捕获到 f1 中(但我希望它不匹配):

  • " - 1Bruce"(前导字符是数字)

这些是实际结果:

  • "-布鲁斯"(f1=布鲁斯)打勾;这行得通
  • " - Bruce Dickinson" (f1=Bruce Dickinson) 勾选;这工作

  • "Bruce"(f1= 未捕获,但表达式是匹配的。这是错误的,因为 Bruce 不匹配可选部分,并且 $ 下一个不匹配 Bruce)

  • "——布鲁斯!" (f1= not cpatured, but expression is a match;这是错误的,因为!,这意味着匹配不会出现在行尾。

我希望:

1
(?:\\s*-\\s*(?P<f1>[A-Za-z][\\w\\s]*))?

会消耗 { - Bruce},它应该离开 !,因为下一个正则表达式标记是 $,它应该会失败;但是,计算机说不,所以我错了,但我不知道为什么:(

  • " - 1Bruce"(f1= 未捕获,但表达式匹配。这是可以理解的,因为整个 {space dash space f1} 序列是可选的,并且因为它不匹配,所以跳过该构造,然后没有其他要处理的内容在输入上;我们打到了行尾)

如果我能做到这一点,我就能让我的其他表达方式按照我想要的方式工作。我需要其他人来激励我以不同的方式思考这个问题。我在这上面花了 2 天没有积极的输出,所以非常令人沮丧。

PS:我正在使用 regex101.com 来测试正则表达式。正则表达式将用作 Rust 应用程序的一部分,该应用程序的正则表达式引擎基于 google 的 RE2。

最终,我需要能够识别由以下各项分隔的名称序列


这里的重点是你不能同时匹配和不匹配。如果您将整个模式设为可选,并且字符串的结尾是强制性的,即使没有任何感兴趣的内容,字符串的结尾也会被匹配 - 总是。

出路是想出一个你感兴趣的子模式。你对名字感兴趣,所以第一个字母是强制性的。在您提供的所有测试用例中,连字符似乎也是强制性的。其他一切都可以是可选的:

1
\\s*-\\s*(?P<f1>([^\\W\\d_])\\w*(?:\\s+\\w+)*)(?:\\s*&\\s*(?P<f2>([^\\W\\d_])\\w*(?:\\s+\\w+??)*))*$

查看正则表达式演示(\\s 被替换为 \\h\
添加到否定字符类中只是为了演示目的,因为它是一个多行演示)。

请注意,我将 [a-zA-Z] 替换为 [^\\W\\d_] 以使模式更灵活([^\\W\\d_] 只匹配任何字母)。