RegEx-两个标记之间的文本,其中一个是可选的



使用RegEx,是否有方法提取2个标记之间的所有文本,其中第二个标记是可选的?

例如:

MARK1 allthetext I need t0 extr4ct i$ here unt.l I_will-find (MARK2 | MARK3 | ANYENDMARK)

MARK1 allthetext I need t0 extr4ct i$ here unt.l I_will-find nothing else

我试着用

(?<=(MARK1 ))([[:ascii:]]*)(MARK2|MARK3|$)?

(?<=(MARK1 ))([[:ascii:]]*)(?=(MARK2|MARK3|$))?

没有成功。


PS:我需要评估C#中的正则表达式。我使用regex101.com作为测试环境

您可以使用

(?<=bMARK1b)(.*?)(?=(?:bMARK2b|bMARK3b|$))

参见演示

注意,我使用的是单行模式,因此.也可以匹配换行符。

b是能够匹配整个单词的单词边界。这样,bMARK1b将与ANYMARK1不匹配。

如果最后有MARKn,您可以使用一个稍微不同的前瞻:(?<=bMARK1b)(.*?)(?=(?:bMARKd+b|$))。参见演示

现在,正则表达式展开:

  • (?<=bMARK1b)-查看后面,确保前面有一个完整的单词MARK1
  • (.*?)-任意0个或更多(但尽可能少(字符(甚至包括由于使用了RegexOptions.Singleline标志而产生的换行符(
  • (?=(?:bMARK2b|bMARK3b|$))-仅当上面的字符后面跟着一个完整的单词MARK2MARK3或字符串末尾时,才匹配它们

您就快到了。让我们从你的第二个表达式开始:

 (?<=(MARK1 ))([[:ascii:]]*)(?=(MARK2|MARK3|$))?
  • 去掉最后的问号:

     (?<=(MARK1 ))([[:ascii:]]*)(?=(MARK2|MARK3|$))
    

    您不需要它:字符串以MARK2、MARK3或行尾结束。这不是可有可无的。

  • *?:替换[[:ascii:]]**使其不贪婪

     (?<=(MARK1 ))([[:ascii:]]*?)(?=(MARK2|MARK3|$))
    

    否则,它将更喜欢线端而不是MARK2或MARK3,因为它可以进行更长的匹配。*?将尝试使最短的匹配成为可能。

  • 您可能还想在MARK2和MARK3前面添加一个空格,以避免匹配以MARK2/3结尾的单词。

     (?<=(MARK1 ))([[:ascii:]]*?)(?=( MARK2| MARK3|$))
    
(?<=MARKd+).*?(?=MARKd+|$)

你可以用这个。请参阅演示。

相关内容

最新更新