如何以特殊顺序提取位于括号之间的文本?

时间:2015-04-02 07:22:23

标签: c# regex string

我有以下字符串:

Find string inside brackets [C#.net [C# Only] [PHP and SQl [MySQL] ] ] and [Vb.net] examples.

我要输出以下内容:

   1 -  [C#.net [C# Only] [PHP and SQl [MySQL] ] ]
   2 -  [C# Only]
   3 -  [PHP and SQl [MySQL] ]
   4 -  [MySQL]
   5 -  [Vb.net]

我的代码是:

string regularExpressionPattern = @"\[([^]]*)\]";
string text = "Find string inside brackets [C#.net [C# Only] [PHP and SQl [MySQL] ] ] and [Vb.net] examples.";
Regex re = new Regex(regularExpressionPattern);
int i = 0 ;
foreach (Match m in re.Matches(text))
{
    i++;
    Console.WriteLine(i + " -  " + m.Value);
}

当前(不正确)输出:

1 -  [C#.net [C# Only]
2 -  [PHP and SQl [MySQL]
3 -  [Vb.net]

2 个答案:

答案 0 :(得分:1)

您需要平衡组。 This并不完全相同,但正则表达式可用于解决您的问题。首先是基本的正则表达式:

\[(?:[^\[\]]|(?<o>\[)|(?<-o>\]))+(?(o)(?!))\]

\[            # Match an opening square bracket
(?:           # Group begin
  [^\[\]]     # Match non-square brackets
|             # Or
  (?<o>\[)    # An opening square bracket which we name 'o'.
|             # Or 
  (?<-o>\])   # A closing square bracket and we remove an earlier square bracket
)+            # Repeat the group as many times as possible
(?(o)(?!))    # Fail if a group named 'o' exists at this point
\]            # Match the final closing square bracket

然后要获得内部匹配,您可以使用前瞻和捕获组,以便获得重叠匹配:

(?=(\[(?:[^\[\]]|(?<o>\[)|(?<-o>\]))+(?(o)(?!))\]))

ideone demo

答案 1 :(得分:1)

我知道正则表达式很精彩,人们用它们做各种奇妙的事情。但简单的事实是,他们是一种痛苦。虽然我确信他们有很多优秀的用户但是杰米·扎金斯基并不是一无所知“有些人在面对问题时会想到”我知道,我会使用正则表达式。“现在他们有两个问题。报价仍然引用。

并不是因为使用正则表达式而不是需要用五线谱进行打击,而是可能只是在展示其他无限的方式?所以我改编了一个普通的,它并不完美;它没有强制使用括号,如果更多的括号接近而不是打开,它会让怪物搞砸,并且它缺少一些可以使它更具可读性的括号:

static class StringExtensions
{
    private static char open = '[';
    private static char close = ']';
    public static string[] Brackets(this string str)
    {
        //Set up vars
        StringBuilder[] builders = new StringBuilder[str.Count(x => x == open)];
        for (int h = 0; h < builders.Count(); h++)
            builders[h] = new StringBuilder();
        string[] results = new string[builders.Count()];
        bool[] tracker = new bool[builders.Count()];
        int haveOpen = 0;
        //loop up string
        for (int i = 0; i < str.Length; i++)
        {
            //if opening bracket
            if (str[i] == open)
                tracker[haveOpen++] = true;
            //loop over tracker
            for (int j = 0; j < tracker.Length; j++)
                if (tracker[j])
                    //if in this bracket append to the string
                    builders[j].Append(str[i]);
            //if closing bracket
            if (str[i] == close)
                tracker[Array.FindLastIndex<bool>(tracker, p => p == true)] = false;
        }
        for (int i = 0; i < builders.Length; i++)
            results[i] = builders[i].ToString();
        return results;
    }
}

然后你可以像

那样使用它
foreach (string part in text.Brackets())
{
    Console.WriteLine(part);
}