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

SA21 abcdef
BKxyz
SA21 abcdef

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

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

最佳答案

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

/\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 是明确的开始/结束字符串 anchor ,/m 修饰符不会影响它们。

模式说明 :
  • \A - 字符串
  • 的开始
  • (?:\n+(?!SA21 abcdef$).*)* - 零个或多个序列:
  • \n+ - 1 个或多个换行符 ...
  • (?!SA21 abcdef$) - 后面没有 SA21 abcdef,即整行
  • .* - 除换行符之外的零个或多个字符
  • \n* - 零个或多个换行符
  • ^ - 一行的开始
  • (SA21 abcdef) - 必须是单行
  • $ - 行尾
  • (?:\n+(?!SA21 abcdef$).*)* - 见上文
  • \z - 字符串结尾。
  • 关于仅在未找到重复行时匹配的正则表达式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38524501/

    10-17 01:43