如何用正则表达式匹配不被特定前缀和后缀包围的字符串 说明输出

问题描述

我需要用Groovy regex匹配由特定前缀和后缀包围的字符串(或字符) not

字符串要求:

  • 不要在两个或三个{字符和0或无限的空格之前-[\{]{2,3}\s*
  • 后跟0或无限空格以及两个或三个}字符-\s*[\{]{2,3}

一些例子:

blah string blah string blah <- two matches
string <- match
{{ string <- match
{{string} <- match
string }} <- match
{string} <- match
{{string}} <- no match
{{ string}} <- no match
{{{string }}} <- no match
{{{ string }}} <- no match

到目前为止,我只剩下(?<!\{{2})string(?!\s*\}{2,})了,但它不能按预期工作,因为:

    负向超前和向后负向不是“与”,因此例如string }}不匹配
  • 后面的负数必须具有固定的长度,因此我不能将0应用于无限的空白

您有任何想法如何使用Groovy regex解决此问题吗?

解决方法

您可以将正则表达式和逻辑结合起来,如下所示:

See this code working here

def list = [
    // match 
    "string","{{ string","{{string}","string }}","{string}",// two matches 
    "blah string blah string blah",// no matches 
    "{{string}}","{{ string}}","{{{string }}}","{{{ string }}}"
]

list.each {
    s -> println s.replaceAll(~/(\{*)( *)(string)( *)(\}*)/,{
        if(it[1].length() != it[5].length() || (it[1].length() == it[5].length() && it[1].length() <= 1 )) {
            it[0] = it[1]+it[2]+"CHANGED"+it[4]+it[5]
        } else it[0]
    })
}

说明

正则表达式(\{*)( *)(string)( *)(\}*)的工作原理如下:

  • (\{*)捕获{的所有实例
  • ( *)捕获空格(以便我们可以放回它们)
  • (string)捕获字符串(您实际上并不需要捕获它,但是它允许您对其进行测试或根据需要进行操作-例如将其大写)
  • ( *)与以前的空间捕获相同
  • (\}*)捕获}的所有实例

代码逻辑遍历list中的每个项目,并通过我们的正则表达式替换函数运行它。 regex replace函数测试捕获以确保满足以下两个条件之一:

  1. {的数量不等于}的数量
  2. {的数量等于}的数量,但是存在一个或更少的{
  • 此匹配{string}string,但不匹配{{string}}

然后,将字符串it[0]替换为相应的部分。您可以根据自己的喜好对其进行修改,但是根据您的原始问题,这似乎是您要查找的输出:

输出

我将string替换为CHANGED

CHANGED
{{ CHANGED
{{CHANGED}
CHANGED }}
{CHANGED}
blah CHANGED blah CHANGED blah
{{string}}
{{ string}}
{{{string }}}
{{{ string }}}