【问题标题】:Match first occurence of a word and ignoring duplicates in a named group匹配第一次出现的单词并忽略命名组中的重复项
【发布时间】:2017-07-12 20:59:43
【问题描述】:

我正在编写一个 PHP 路由器引擎进行练习,目前正在为它做正则表达式。

映射的 URL 可以具有参数模式,并且可以像 {type:varName} 一样写下来。我不想让变量名多次出现,在这种情况下是varName

我目前有这个正则表达式:

{(?<key>[a-zA-Z]{1,4}):(?<name>[a-zA-Z_]\w*\b)(?!.*\1\b)}

(live version here)

问题在于它只检查&lt;key&gt; 组中的重复项,而不检查&lt;name&gt; 组中的重复项。它还发现最后一个发生而不是找到的第一个。

如何使这个正则表达式只匹配&lt;name&gt; 组的第一次出现而不匹配第一次匹配的重复项?


示例

当你有这样的模式时:

{s:varName}-{i:varName}-{s:varName}

只有第一个 {s:varName} 应该匹配,其他 2 个不应该匹配。

当有这样的模式时:

{i:varName1}-{d:varName1}-{i:varName2}-{i:varName3}-{m:varName3}

{i:varName1}{i:varName2}{i:varName3} 应该匹配。


更新

感谢@sln,我最终得到了这个正则表达式:

{(?<key>[a-zA-Z]{1,4}):(?<name>[a-zA-Z_]+\b)}(?:(?!.*{[a-zA-Z_]{1,4}:\2))

唯一的问题是它与第一次出现的不匹配,而是与找到的最新匹配。

我在这里做错了什么?

【问题讨论】:

  • 不要进行全局搜索,只进行搜索。这只会找到第一个。名称组中的重复是什么意思? {(?&lt;key&gt;[a-zA-Z]{1,4}):(?&lt;name&gt;[a-zA-Z_]\w*\b)}(?!.*{\1:\2})
  • 我所说的名称组中的重复是指&lt;key&gt; 组可以有多个i,但&lt;name> 组不能有多个varName .全局搜索是什么意思?
  • 我很困惑,例如,不可能有这样的模式:{s:varName}-{i:varName}-{s:varName},但允许这样的模式:{i:varName1}-{i:varName2}-{i:varName3}
  • 我刚刚给了你正则表达式{(?&lt;key&gt;[a-zA-Z]{1,4}):(?&lt;name&gt;[a-zA-Z_]\w*\b)}(?!.*{\1:\2})
  • @sln 仍然匹配 &lt;name&gt; 组的重复项:regex101.com/r/H4cuDJ/1

标签: php regex


【解决方案1】:

您可以制定解决方法。设置代理名称(多组不重复),在代码中得到你想要的。

如果你想要正则表达式:

{s:varName}-{i:varName}-{s:varName}

写出来:

{s:varName-1}-{i:varName-2}-{s:varName-3}

并写一些逻辑:

  • 获取varName-*varName-1varName-2varName-3)的所有组,
  • 得到你想要的(例如第一次出现它是varName-1)。

对于这个正则表达式:

{i:varName1}-{d:varName1}-{i:varName2}-{i:varName3}-{m:varName3}

写:

{i:varName1-1}-{d:varName1-2}-{i:varName2-1}-{i:varName3-1}-{m:varName3-2}

同样的逻辑:

  • 获取varName1-*varName1-1varName1-2)、varName2-*varName3-* 等的所有组。
  • 从所有多组中获取*-1varName1-1varName2-1varName3-1

我使用此解决方法,因为其他一些语言(例如 Java)不支持重复的组名。

【讨论】:

    猜你喜欢
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    相关资源
    最近更新 更多