我需要在'('和')'字符之间获取所有字符。
var str = "dfgdgdfg (aaa.bbb) sfd (c) fdsdfg ( ,ddd (eee) )";
在这个例子中,我需要得到3个字符串:
(aaa.bbb)
(c)
( ,ddd (eee) )
我要写什么模式?请帮忙。
答案 0 :(得分:4)
尝试这样的事情:
\(([^)]+)\)
编辑:实际上,完全最后一位工作 - 这个表达式没有正确捕获最后一个子字符串。我有CW这个答案,以便有更多时间的人可以充实它,使其正常工作。
答案 1 :(得分:2)
.NET支持使用平衡组在正则表达式中进行递归。例如,请参阅http://blog.stevenlevithan.com/archives/balancing-groups
强烈推荐答案 2 :(得分:1)
您需要一个词法分析器/解析器组合,或者使用具有堆栈支持的词法分析器。但正确的正则表达式将让你无处可去。
答案 3 :(得分:1)
你需要递归才能做到这一点。
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)
答案 4 :(得分:1)
不是说这比Regex好,但这是另一种选择
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;
}
}
}
答案 5 :(得分:1)
您想使用.net正则表达式的平衡匹配组功能。
var s = "dfgdgdfg (aaa.bbb) sfd (c) fdsdfg ( ,ddd (eee) )";
var exp = "\([^()]*((?<paren>\()[^()]*|(?<close-paren>\))[^()]*)*(?(paren)(?!))\)";
var matches = Regex.Matches(s,exp);
答案 6 :(得分:0)
如果您只需要处理单级嵌套,则可以使用一对互斥模式。
(\([^()]*\))
(\([^()]*\([^()]*\)[^()]*\))
或者您可以跳过正则表达式并直接解析字符串。递增状态变量(,递减打开),并在返回零时打印一行。
答案 7 :(得分:0)
正如其他人已经提到的:正则表达式不适合这样的任务。但是,如果您的括号不超过嵌套的固定数量,您可以这样做,但如果嵌套可以是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的递归正则表达式匹配功能,但我个人不会去:在正则表达式中传递递归会导致疯狂! (当然不是真的,但正则表达式很难理解和混合递归到混合,不会让它更清晰IMO)
我只想写一个看起来像这个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#我认为。