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