【问题标题】:Regex Capture one word OR two words in quotes正则表达式在引号中捕获一个单词或两个单词
【发布时间】:2020-06-01 12:01:22
【问题描述】:

我正在尝试在我的搜索中实现 gmail 样式过滤器,但我遇到了这个正则表达式问题。我需要在引号中捕获一个单词或两个单词(但没有引号本身)这是 PCRE (PHP)

即。

name:mark

期望的结果:第一个捕获组应该是标记

name:"mark"

期望的结果:第一个捕获组应该是标记

name:"mark wilson"

期望的结果:第一个捕获组应该是标记,第二个捕获组应该是 wilson

name:mark wilson

期望的结果:第一个捕获组应该是标记,威尔逊被忽略

我得到的最接近的是 name:(\w+|\"\w+(?>\"|\s([a-z.'-]+\"))) 它完美地捕获了示例 1,但示例 2仍然包括引号,示例 3 最终为:

第 1 组:“mark wilson”(包括引号)

第 2 组:wilson"(包括报价)

我已经尝试过前瞻和后瞻,但我也没有得到任何结果

任何帮助将不胜感激。 tia

【问题讨论】:

  • 你可能想使用多重匹配,比如(?:\G(?!\A)\h*"?|:"?)\K\w+,见this regex demo
  • 匹配项需要分组才能提取用于搜索目的。不幸的是,这不仅仅是布尔匹配操作的问题,否则这将起作用。
  • 主要的一点是你不能对任意数量的组这样做,你必须在模式中指定它们。比如regex101.com/r/qm59Ae/2。您可以使用 \w+:(?|(\w+)|"(\w+)(?:\h+(\w+))?(?:\h+(\w+))?") 并在末尾添加更多 (?:\h+(\w+))? 模式以支持最多 N 个可选单词
  • 兄弟,我想你刚刚明白了。 \w+:(?|(\w+)|"(\w+)(?:\h+(\w+))?(?:\h+(\w+))?") 似乎工作得很好@WiktorStribiżew 你能把这个作为答案发布吗?我会把它标记为正确的。

标签: regex pcre


【解决方案1】:

1 选项可以使用if/else clause,它将在第 2 组中给出标记,在第 3 组中给出 wilson。第一组将捕获 ",它可用于 if else 检查组 1 的存在。

\w+:(")?(\w+(?:\h+(\w+))?)(?(1)")

Regex demo

如果名字后面的空格不应该在那里,您也可以将其分组并将值放在第 3 组和第 4 组中

\w+:(")?((\w+)(?:\h+(\w+))?)(?(1)")

Regex demo

您还可以获取或不获取引号之间的单个值,或者使用 branch reset group 捕获捕获组中的第一个或第二个名称


\w+:(?|"(\w+)(?:\h+(\w+))?"|(\w+))

说明

  • \w+:匹配1+字字符
  • (?|分支重置组
    • "(\w+)捕获组1,匹配1+字字符
    • (?:非捕获组
      • \h+ 匹配 1+ 个水平空白字符
      • (\w+)捕获组2,匹配1+字字符
    • )? 关闭群组并设为可选
    • "匹配"
    • |或者
    • (\w+)捕获组1,匹配1+字字符
  • )关闭分支重置组

Regex demo

【讨论】:

  • 这非常接近,但是在第 4 个示例 name:mark wilson 即使它没有被引号包围,它仍然在第 4 个捕获组中捕获 wilson。如果有人搜索 name:mark something-thats-not-a-name,这可能会导致问题
  • @Wazimshizm 所以应该总是用引号括起来?
  • @Wazimshizm 或者喜欢这个\w+:(")?((\w+)(?:\h+(\w+))?)(?(1)")(?!\S)regex101.com/r/dsZmJq/1
  • 或者使用分支重置组\w+:(?|(\w+)(?:\h+(\w+))?|"(\w+)(?:\h+(\w+))?")(?!\S)regex101.com/r/5XkDuu/1
  • 不,它并不总是必须用引号括起来,但如果没有引号,则只会捕获第一个名称。一个真实搜索的例子可能是24 Main St, Seattle name:Doug date:06152020 我现在只是想提取名称部分。如果有人想指定姓氏,则必须用引号括起来,否则可能会无意中找到搜索的其他部分。
【解决方案2】:

主要的一点是你不能对任意数量的组这样做,你必须在设计时在模式中指定它们。

您可以将这样的模式与branch reset group 一起使用:

\w+:(?|(\w+)|"(\w+)(?:\h+(\w+))?(?:\h+(\w+))?")

请参阅regex demo。在末尾添加更多 (?:\h+(\w+))? 模式,以支持最多 N 个可选单词。

详情

  • \w+: - 1+ 个单词字符,然后是 :
  • (?|(\w+)|"(\w+)(?:\h+(\w+))?(?:\h+(\w+))?") - 一个分支重置组,其中组共享相同的 ID:
    • (\w+) - 第 1 组:一个或多个单词字符
    • | - 或
    • "(\w+)(?:\h+(\w+))?(?:\h+(\w+))?" -
      • " - 一个 " 字符
      • (\w+) - 第 1 组:一个或多个单词字符
      • (?:\h+(\w+))? - 序列的可选出现:
      • \h+ - 1 个或多个水平空格
      • (\w+) - 第 2 组:一个或多个单词字符
      • (?:\h+(\w+))?" - 同上,但使用第 3 组等。

【讨论】:

    猜你喜欢
    • 2020-06-09
    • 1970-01-01
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多