C# 使用.NET正则表达式查找括号之间的所有字符

C# 使用.NET正则表达式查找括号之间的所有字符,c#,.net,regex,C#,.net,Regex,我需要获取“(”和“)”字符之间的所有字符 在本例中,我需要获得3个字符串: (aaa.bbb) (c) ( ,ddd (eee) ) 我要写什么样的图案?请帮帮我。试试这样的方法: \([^)]+)\ 编辑:实际上,这对最后一位非常有效-此表达式无法正确捕获最后一个子字符串。我已经给出了这个答案,以便有更多时间的人能够充实它,使其正常工作。您要么需要一个lexer/解析器组合,要么使用一个支持堆栈的lexer。但是regex本身并不会让你有任何收获。你需要递归才能做到这一点 Per

我需要获取“(”和“)”字符之间的所有字符

在本例中,我需要获得3个字符串:

(aaa.bbb)
(c)
(    ,ddd   (eee) )

我要写什么样的图案?请帮帮我。

试试这样的方法:

\([^)]+)\


编辑:实际上,这对最后一位非常有效-此表达式无法正确捕获最后一个子字符串。我已经给出了这个答案,以便有更多时间的人能够充实它,使其正常工作。

您要么需要一个lexer/解析器组合,要么使用一个支持堆栈的lexer。但是regex本身并不会让你有任何收获。

你需要递归才能做到这一点

Perl示例:

#!/usr/bin/perl

$re = qr  /
     (                      # start capture buffer 1
        \(                  #   match an opening paren
        (           # capture buffer 2
        (?:                 #   match one of:
            (?>             #     don't backtrack over the inside of this group
                [^()]+    #       one or more 
            )               #     end non backtracking group
        |                   #     ... or ...
            (?1)            #     recurse to opening 1 and try it again
        )*                  #   0 or more times.
        )           # end of buffer 2
        \)                  #   match a closing paren
     )                      # end capture buffer one
    /x;


sub strip {
my ($str) = @_;
while ($str=~/$re/g) {
    $match=$1; $striped=$2;
    print "$match\n";
    strip($striped) if $striped=~/\(/;
    return $striped;
    }
}


$str="dfgdgdfg (aaa.bbb) sfd (c) fdsdfg (   ,ddd   (eee) )";

print "\n\nstart=$str\n";

while ($str=~/$re/g) { 
    strip($1) ;
}
输出:

start=dfgdgdfg (aaa.bbb) sfd (c) fdsdfg (   ,ddd   (eee) )
(aaa.bbb)
(c)
(   ,ddd   (eee) )
(eee)

如果只需要处理单个嵌套级别,则可以使用一对互斥模式

(\([^()]*\))
(\([^()]*\([^()]*\)[^()]*\))

或者您可以跳过正则表达式,直接解析字符串。将状态变量递增(,递减on),并在返回零时打印一行。

.NET支持使用平衡组在正则表达式中递归。比如说,


正如其他人已经提到的那样,我们强烈推荐使用regex:regex不太适合这样的任务。但是,如果括号没有超过固定数量的嵌套,您可以这样做,但是如果嵌套可以是3个或更多,正则表达式将成为编写(和维护)的麻烦。查看与括号匹配的正则表达式,其中最多有一个嵌套括号:

\((?:[^()]|\([^)]*\))*\)
这意味着:

\(         # match the character '('
(?:        # start non-capture group 1 
  [^()]    #   match any character not from the set {'(', ')'}
  |        #   OR
  \(       #   match the character '('
  [^)]*    #   match any character not from the set {')'} and repeat it zero or more times
  \)       #   match the character ')'
)*         # end non-capture group 1 and repeat it zero or more times
\)         # match the character ')'
3的版本会让你的眼睛流血!您可以使用.NET的递归正则表达式匹配功能,但我个人不这么认为:在正则表达式中散布递归会导致疯狂!(当然不是真的,但是regex很难理解,混合递归到混合中,这在我看来并不能让它变得更清晰)

我只想编写一个类似于以下Python代码段的小方法:

def find_parens(str):

    matches = []
    parens = 0
    start_index = -1
    index = 0

    for char in str:
        if char == '(':
            parens = parens+1
            if start_index == -1:
                start_index = index
        if char == ')':
            parens = parens-1
            if parens == 0 and start_index > -1:
                matches.append(str[start_index:index+1])
                start_index = -1
        index = index+1

    return matches

for m in find_parens("dfgdgdfg (aaa.bbb) sfd (c) fdsdfg (   ,ddd   (eee) )"):
    print(m)
其中打印:

(aaa.bbb)
(c)
(   ,ddd   (eee) )

我不熟悉C#,但是上面的Python代码读起来就像伪代码一样,我想转换成C#不会花费太多精力。

并不是说这比正则表达式好,但这里有另一个选择

    public static IEnumerable<string> InParen(string s)
    {
        int count = 0;
        StringBuilder sb = new StringBuilder();
        foreach (char c in s)
        {
            switch (c)
            {
                case '(':
                    count++;
                    sb.Append(c);
                    break;
                case ')':
                    count--;
                    sb.Append(c);
                    if (count == 0)
                    {
                        yield return sb.ToString();
                        sb = new StringBuilder();
                    }
                    break;
                default:
                    if (count > 0)
                        sb.Append(c);
                    break;
            }
        }
    }
公共静态IEnumerable InParen(字符串s)
{
整数计数=0;
StringBuilder sb=新的StringBuilder();
foreach(字符c在s中)
{
开关(c)
{
格“(”:
计数++;
sb.附加(c);
打破
案例“)”:
计数--;
sb.附加(c);
如果(计数=0)
{
让某人返回字符串();
sb=新的StringBuilder();
}
打破
违约:
如果(计数>0)
sb.附加(c);
打破
}
}
}

您想使用.net正则表达式的平衡匹配组功能

var s = "dfgdgdfg (aaa.bbb) sfd (c) fdsdfg (   ,ddd   (eee) )";
var exp = "\([^()]*((?<paren>\()[^()]*|(?<close-paren>\))[^()]*)*(?(paren)(?!))\)";
var matches = Regex.Matches(s,exp);
var s=“dfgdgdfg(aaa.bbb)sfd(c)fdsdfg(,ddd(eee))”;
var exp=“\([^()]*((?\()[^()])*(?\)[^()]*)*(?(paren)(?!)\)”;
var matches=Regex.matches(s,exp);

嵌套模式?那是不规则的。如果str是“dfgdfg(aaa.bbb)sfd(c)fdsdfg”,那么获取大括号中所有字符的模式是什么?:)@肯尼特:呵呵,他们什么时候才能学会@Net正则表达式可以处理嵌套模式!所以这是可能的。见下面我的答案。
var s = "dfgdgdfg (aaa.bbb) sfd (c) fdsdfg (   ,ddd   (eee) )";
var exp = "\([^()]*((?<paren>\()[^()]*|(?<close-paren>\))[^()]*)*(?(paren)(?!))\)";
var matches = Regex.Matches(s,exp);