【问题标题】:Regex includes two matches in first match正则表达式在第一场比赛中包括两个比赛
【发布时间】:2017-01-18 09:18:11
【问题描述】:

我有this regex,它试图找到单独的 STEP 行并将其分为参考号、类和属性的三个组:

#14=IFCEXTRUDEDAREASOLID(#28326,#17,#9,3657.6);

变成

[['14'], ['IFCEXTRUDEDAREASOLID'], ['#28326,#17,#9,3657.6']]

有时这些行有任意换行符,尤其是在属性之间,所以我在正则表达式中放了一些 \s。然而,这导致了一个有趣的错误。该模式现在将两行匹配到每个匹配项中。

如何调整正则表达式以仅捕获一行,即使它们有换行符?只是为了好奇,为什么它会在第二行之后停止,而不是一直持续到最后一行?

【问题讨论】:

  • 在我看来您想使用类似#(\d+)\s*=\s*([a-zA-Z0-9]+)\s*\(([\s\S]*?)\); 的东西。或^#(\d+)\s*=\s*([a-zA-Z0-9]+)\s*\(([\s\S]*?)\);$(带有多行选项)。
  • @WiktorStribiżew 非常感谢!这似乎有效。添加答案,我会接受它是正确的。速度加分:)
  • 是的,当然,我会添加解释。
  • 我认为使用 \S 有点矫枉过正
  • @Maverick_Mrt:这不是“矫枉过正”,[\s\S]*? / (?s:.*?) 是匹配未知字符串直到第一次出现多字符分隔符的正确方法(之一)。有一种方法可以通过展开它来提高效率,但通常情况下,人们在看到量化组内的前瞻时会感到害怕。

标签: regex step ifc


【解决方案1】:

你现在每次匹配 2 行的原因是 \s 匹配任何空格,如果匹配后有换行符,\s* 将全部抓取。

使用

/^#(\d+)\s*=\s*([a-zA-Z0-9]+)\s*\(((?:'[^']*'|[^;'])+)\);/gm

this regex demo

详情

  • ^ - 行首
  • # - 一个井号
  • (\d+) - 第 1 组:一位或多位数字
  • \s*=\s* - = 用可选空格括起来
  • ([a-zA-Z0-9]+) - 第 2 组捕获 1+ 个字母数字
  • \s*\( - 0+ 个空格和一个 (
  • ((?:'[^']*'|[^;'])+) - 第 3 组捕获 '...' 子字符串('[^']*',内部不允许有 ')或(|)除 ;' 之外的 1+ 个字符([^;']+)李>
  • \); - ); 序列

否定字符类解决方案suggested by Maverick_Mrt 适用于特定情况,但是一旦使用([\s\S]*?) 捕获的文本包含否定字符,匹配就会失败。

【讨论】:

  • 如果我们考虑模式,我认为考虑';'并不难不会存在于括号内。
  • @Maverick_Mrt:我更喜欢通用方法。我们不知道分号是否总是不存在。它看起来像一些 Excel(?) 公式,并且在某些语言环境中使用了分号
  • #1=IFCOWNERHISTORY(#89024,#44585,$,.NOCHANGE.,$,$,$,11907208);\n90);如果我假设按照您的方法可以有任何东西,这将失败....regex101.com/r/RHIu0r/8
  • @Maverick_Mrt 这不是有效的 STEP 行。分号总是结束一行,除非它们包含在字符串 ';;;;' 中。并且 90);-part 应该被忽略。
【解决方案2】:

你可以试试这个:

#(\d+)\s*=\s*([a-z0-9]+)\s*\([^;]*\);

Your updated link

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    • 2022-12-24
    • 2018-07-26
    • 1970-01-01
    相关资源
    最近更新 更多