【问题标题】:Regex that only matches when no duplicate lines are found仅在未找到重复行时匹配的正则表达式
【发布时间】:2023-03-25 02:12:01
【问题描述】:

我有一个这样的多行字符串:

SA21 abcdef
BKxyz
SA21 abcdef

我需要一个仅当^SA21 abcdef$ 行出现一次时才匹配的正则表达式。所以它不应该匹配第一个例子,但它应该匹配这个:

BK udsia
SA21 abcdef
BKxyz

我试图捕获该行并确保它仅在以后找不到同一行时才匹配:/(^SA21 abcdef$)(?!\1)/m regex101 但这不起作用,因为它可能总是匹配最后一行...

【问题讨论】:

  • 试试\A(?:(?!^SA21 abcdef$).)*(^SA21 abcdef$)(?:(?!^SA21 abcdef$).)*\z(只是想知道这是否是正确的方向)。
  • 为什么不直接匹配它,然后检查有多少匹配项,然后将if 设为?
  • @FlorianPeschka 我不能轻易使用代码,因为我们使用来自 dsl 的正则表达式
  • @WiktorStribiżew 看起来不错...让我测试一下
  • 为什么要求不要重复字符串? :) 我认为你应该问如何让它更快、更高效、更健壮。

标签: regex multiline


【解决方案1】:

你想要的正则表达式应该只匹配 line 如果该行在该行的单次出现之前或之后不存在。这是通过缓和的贪婪令牌实现的:

/\A(?:(?!^SA21 abcdef$).)*(^SA21 abcdef$)(?:(?!^SA21 abcdef$).)*\z/ms

regex demo

(?:(?!^SA21 abcdef$).)* 是匹配除SA21 abcdef 行开头之外的任何文本的标记。 /s 修饰符是必需的,以便 . 可以匹配换行符。

但是,该构造消耗资源,展开它是个好主意:

/\A(?:\n+(?!SA21 abcdef$).*)*\n*^(SA21 abcdef)$(?:\n+(?!SA21 abcdef$).*)*\z/m

another demo

注意\A\z 是明确的开始/结束字符串 锚,/m 修饰符不会影响它们。

模式说明

  • \A - 字符串开头
  • (?:\n+(?!SA21 abcdef$).*)* - 零个或多个序列:
    • \n+ - 1 个或多个换行符 ...
    • (?!SA21 abcdef$) - 后面没有SA21 abcdef,这是整行
    • .* - 除换行符以外的零个或多个字符
  • \n* - 零个或多个换行符
  • ^ - 行首
  • (SA21 abcdef) - 必须为单行
  • $ - 行尾
  • (?:\n+(?!SA21 abcdef$).*)* - 见上文
  • \z - 字符串结束。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-18
    • 2015-03-24
    相关资源
    最近更新 更多