仅在不包含在其他模式中时匹配的正则表达式模式

时间:2019-08-06 09:38:11

标签: regex ruby regex-lookarounds regex-negation

我试图了解如何制作仅与某个模式匹配的正则表达式,如果该模式不包含在另一个模式中。

在下面的示例中,仅当破折号不在[code] [/ code]标记中时,我才想匹配它们。

---------

[code]
-------------------------------------------------------------------------------------

Some text

-----------------

Some other text

-------------------------------------------------------------------------------------
test

[/code]

我已经搜索了有关前行和后行的解释,但无法理解它是否以及如何适合我的需求。

我想同时使用负向后看和负向后看,但似乎无法在负向后看模式中使用+或*。

例如,这是行不通的(因为后面的负面表情中有+)

/(?<!\[code\].+?)(-{5,100})(?!.+?\[\/code\])/m

如何以其他方式实现这一目标?

2 个答案:

答案 0 :(得分:2)

如果标签没有嵌套,则一种可能性是从开始标签到结束标签匹配,以匹配您不想要的标签。然后使用交替方式在一组中捕获您想要的内容,在这种情况下为5到100倍的连字符。

\[code\](?:(?!\[\/?code\]).)*\[\/code]|(-{5,100})/m

说明

  • \[code\]匹配[code]
  • (?:非捕获组
    • (?!\[\/?code\]).断言[code]后是否用可选的/来代替右边的[,然后匹配任何字符。
  • )*重复非捕获组并重复0次以上
  • \[\/code]匹配[/code]
  • |
  • (-{5,100})在第1组中捕获,匹配连字符5-100倍

Regex demo

答案 1 :(得分:2)

我不认为正则表达式是此处工作的正确工具。

str = <<END
---------
[code]
-------------------------------------------------------------------------------
Some text
----------------------------------
Some other text
-------------------------------------------------------------------------------
test
[/code]
------------
---
[code]
Some text
-------------------------------------------
[/code]
------------
END

within = false
str.split("\n").select do |line|
  case line
  when "[code]"
    within = true
    false
  when "[/code]"
    within = false
    false
  else
    within == false
  end
end
  #=> ["---------", "------------", "---", "------------"] 

如果不推荐使用我喜欢的flip-flip operator,我会使用它。

 str.split("\n").reject do |line|
   true if line == "[code]"..line == "[/code]"
 end
   #=> ["---------", "------------", "---", "------------"]

Hold the phone!看起来Matz拥有un-deprecated it! (滚动到结束。)