正则表达式:仅替换非嵌套匹配

时间:2012-08-23 18:11:09

标签: c# .net regex

给出如下文字:

This is my [position].
Here are some items:
[items]
    [item]
         Position within the item: [position]
    [/item]
[/items]

Once again, my [position].

我需要匹配[position]中的第一个和最后一个[items]...[/items],但 Regex.Replace(input, @"\[position\]", "replacement value") 中的[位置]。这是否可以使用正则表达式?到目前为止,我只有:

{{1}}

但这取代了我想要的东西。

3 个答案:

答案 0 :(得分:2)

正如Wug所说,正则表达式并不算数。更简单的选择是找到您正在寻找的所有标记的位置,然后迭代它们并相应地构建输出。也许是这样的:

public string Replace(input, replacement)
{
    // find all the tags
    var regex = new Regex("(\[(?:position|/?item)\])");
    var matches = regex.Matches(input);

    // loop through the tags and build up the output string
    var builder = new StringBuilder();
    int lastIndex = 0;
    int nestingLevel = 0;
    foreach(var match in matches)
    {
        // append everything since the last tag;
        builder.Append(input.Substring(lastIndex, (match.Index - lastIndex) + 1));

        switch(match.Value)
        {
            case "[item]":
                nestingLevel++;
                builder.Append(match.Value);
                break;
            case "[/item]":
                nestingLevel--;
                builder.Append(match.Value);
                break;
            case "[position]":
                // Append the replacement text if we're outside of any [item]/[/item] pairs
                // Otherwise append the tag
                builder.Append(nestingLevel == 0 ? replacement : match.Value);
                break;
        }
        lastIndex = match.Index + match.Length;
    }

    builder.Append(input.Substring(lastIndex));
    return builder.ToString();
}

(免责声明:未经过测试。甚至尝试编译。请提前道歉,以避免不可避免的错误。)

答案 1 :(得分:0)

你可以maaaaaybe逃脱:

Regex.Replace(input,@"(?=\[position\])(!(\[item\].+\[position\].+\[/item\]))","replacement value");

我不知道,我讨厌这样的人。但这是xml解析的工作,而不是正则表达式。如果括号实际上是括号,只需用胡萝卜搜索并替换它们,然后用xml解析。

答案 2 :(得分:0)

如果你检查两次怎么办?像,

s1 = Regex.Replace(input, @"(\[items\])(\w|\W)*(\[\/items\])", "")

这会给你:

This is my [position].
Here are some items:
Once again, my [position].

如您所见,提取项目部分。然后在s1上你可以提取你想要的位置。像,

s2 = Regex.Replace(s1, @"\[position\]", "raplacement_value")

这可能不是最好的解决方案。我努力在正则表达式上解决它但没有成功。