我会努力做到这一点简单易行,因为我很难说出我正在尝试做什么。
基本上我正在尝试匹配令牌内的令牌或整个令牌。我下面的正则表达式有效,除非有一个随机{
不是令牌的一部分。
示例:
Tokens start with "{:" and end with ":}"
{:MyTokenFunction({:MyTokenParameter:}):}
^--- WORKS as it matches "{:MyTokenParameter:}"
{:MyTokenFunction(5):}
^--- WORKS as it matches "{:MyTokenFunction(5):}"
{:MyTokenFunction(random{string}):}
^--- The "{" causes no matches, but should match the entire string.
这是我所匹配的正则表达式的一个彩色示例。 *前两个例子是正确的,但第三个例子应该完全匹配,它根本不匹配。
这是我正在使用的正则表达式,它与第三个例子有问题:
\{\:[^\{]+?\:\}
对于我的生活,我无法弄清楚如何绕过造成0场比赛的{
。
我尝试使用lookbehinds / aheads,但我没有太多运气。虽然我当然喜欢快速回答;我想要解释正则表达式实际上做得更多。我做了很多搜索试图弄清楚这一点,但由于我的“标记”被多个字符包裹并且开始/结束不一样,所以无法找到一个好例子。
由于
答案 0 :(得分:2)
您的正则表达式匹配以{:
开头的字符串,以:}
结尾,并且之间没有任何{
。请注意?
之后显示的+
,这会使其变得非贪婪。它上面有很多文档。
在你的情况下,
{:MyTokenFunction(random{string}):}
中间有{string}
部分,由于花括号而拒绝它。
如果这是一个有效的字符串,那么该条件不应该存在,应该取出。例如
\{\:.+?\:\}
但是,如果该条件是限制,那么您的字符串无效输入。
答案 1 :(得分:2)
这是一个可爱的问题,因为它需要我们平衡开始和结束令牌,这是一个.NET恰好具有现成功能的任务:平衡组。
让我们分别看一下。
为什么你的正则表达式不起作用?
[^\{]+
表示"匹配任何数量不是{
"
显然,这无法匹配{
中的{3}
简单解决方案(有警告)
{:.*:}
这将贪婪地匹配开始和结束大括号之间的所有内容。如果每行只有一个标记(如果您不处于DOTALL模式),则此方法有效。
但是,如果你在同一行上有两个令牌,那么正则表达式会同时使用它们。如果您处于DOTALL模式,这将占用所有令牌。这就是你要知道的。
请参阅demo
更复杂(但更强大)的解决方案
为了避免上述问题,我们需要平衡大括号。在Perl或PCRE中,我们将使用递归。由于我们在.NET中,我们将使用平衡组,这是.NET引擎的一个很好的功能。
这是一种方法。这是一个满口的,但我会在下面解释。
(?:{:(?<counter>)(?:(?!{:|:}).)*)+(?::}(?<-counter>)(?:(?!{:|:}).)*)+(?<=:})(?(counter)(?!))
请参阅demo
这是如何运作的?
这是相同的正则表达式,但在自由间隔模式下,带有注释。我建议在代码中使用此版本,因为它使维护更容易。
(?x) # free-spacing mode
(?:{:(?<counter>)(?:(?!{:|:}).)*)+ # match all the opening {: and increment counter
(?::}(?<-counter>)(?:(?!{:|:}).)*)+ # # match all the closing {: and decrement counter
(?<=:}) # negative lookbehind: we must close tiwht a :} (backtrack if we went too far)
(?(counter)(?!)) # if the counter has not been decremented to zero, then fail (ensuring balance)
潜在调整
根据您的需要,可能存在调整:例如,如果您希望令牌能够跨越多行。请告诉我们。