如何找到以“!!”结尾的文本块,同时仍然允许“!”正则表达式中的字符?

时间:2016-03-03 04:30:55

标签: php regex

我有一个特殊的用例,我需要检测以!!结尾的段落。段落中正常出现!(单个),但是当找到!!时块会结束。

例如:

test foo bar !!
longer paragraph this time!
goes on and on
and then stops !!

应该被检测为两个单独的匹配,一个覆盖第一行,另一个(单独)覆盖第2,3和4行。这使它总共有2个匹配。

(最好它应该使用多线模式,因为它是使用此模式的更大正则表达式的一部分。)

我将如何做到这一点?我试过[^!!]*对我来说,找到尽可能多的非!!字符,但我不确定如何利用它,更糟糕的是它仍然发现单次出现{{1} }。

4 个答案:

答案 0 :(得分:1)

正则表达式中有一个常用的习惯用法用于转义序列。 (比如" \ n"在一个字符串中。)你可以在这里使用相同的概念。

诀窍是匹配NOT第一个字符,或第一个字符后跟有效的第二个字符。

在你的情况下,那将是:

# All together:
(?:[^!]|![^!])*    # zero or more
(?:[^!]|![^!])+    # one or more

这对备选方案描述了段落中的所有字符。因此,您可以重复0次(*)或一次或多次(+),具体取决于您在其余模式中的操作。

^([!]?[^!]+[!]?[^!]+)*[!]{2}$/gm

(显然,如果你愿意的话,你最后可以匹配!'

答案 1 :(得分:1)

/^([!]?[^!]+[!]?[^!]+)*.?[!]{2}$|^([!]?[^!]+[!]?[^!]+)*[^!]?[!]?$/gm

这个正则表达式对我有用。它确保任何单一!字符由非分隔!人物,但不必有任何单身!字符。它适用于多线模式。这还有一个额外的好处,即在出现" !!"之前提取文本。因为我认为你想要使用它。

{{1}}

这个稍微长一点的正则表达式捕获了最终结束后发生的文字!! (即,如果文件在!!和EOF之间有文本)。我不建议使用捕获组,但是在我的正则表达式检查器中,它们似乎没有正常工作(可能只是一个实现故障,但是,因为捕获组看起来应该正常工作)。

答案 2 :(得分:0)

试试这个:

([\w\s!]+?\!{2})

DEMO

输出:

MATCH 1
1.  [0-15]  `test foo bar !!`
MATCH 2
1.  [15-76] `
longer paragraph this time!
goes on and on
and then stops !!`

(?:\n?([\w\s!]+?)\s?\!{2})

DEMO

输出:

MATCH 1
1.  [0-12]  `test foo bar`
MATCH 2
1.  [16-73] `longer paragraph this time!
goes on and on
and then stops`

答案 3 :(得分:0)

使用lookahead

尝试使用正则表达式

版本#1

/(?<=!!|^).*?(?=!!)/gms

请参阅https://regex101.com/r/cQ0wC0/2

结果应为

  

输出:

     
      
  • test foo bar

  •   
  • 这次更长的段落!   继续下去   然后停止

  •   

版本#2

由于OP希望在!!之后捕获最后一段文本,即使它没有以爆炸标志结束。

/(?<=!!|^).*?(?=!!)|(?<=!!).*$/gms

请参阅演示https://regex101.com/r/cQ0wC0/4

  

INPUT:

test foo bar !!
longer paragraph this time!
goes on and on
and then stops !!
longer paragraph this time!
goes on and on
  

输出:

     
      
  • test foo bar

  •   
  • 这次更长的段落!   继续下去   然后停止

  •   
  • 这次更长的段落!   

  •