C# 正则表达式嵌套括号
我有以下字符串:C# 正则表达式嵌套括号,c#,.net,regex,string,C#,.net,Regex,String,我有以下字符串: a,b,c,d.e(f,g,h,i(j,k)),l,m,n 您知道如何构建一个只返回“第一级”括号的正则表达式吗 [0] = a,b,c, [1] = d.e(f,g,h,i.j(k,l)) [2] = m,n (?<head>[a-zA-Z._]+\,)*(?<body>[a-zA-Z._]+[(].*[)])(?<tail>.*) 目标是保持括号中具有相同索引的部分嵌套,以便将来操作 多谢各位 编辑 尝试改进示例 想象一下我有这根绳
a,b,c,d.e(f,g,h,i(j,k)),l,m,n
您知道如何构建一个只返回“第一级”括号的正则表达式吗
[0] = a,b,c,
[1] = d.e(f,g,h,i.j(k,l))
[2] = m,n
(?<head>[a-zA-Z._]+\,)*(?<body>[a-zA-Z._]+[(].*[)])(?<tail>.*)
目标是保持括号中具有相同索引的部分嵌套,以便将来操作
多谢各位
编辑
尝试改进示例
想象一下我有这根绳子
username,TB_PEOPLE.fields(FirstName,LastName,TB_PHONE.fields(num_phone1, num_phone2)),password
我的目标是将字符串转换为动态查询。
然后,不以“TB_”开头的字段我知道它们是主表的字段,否则我知道括号内的informandos字段与另一个表相关。
但是我很难检索所有“第一级”字段,因为我可以将它们从相关表中分离出来,我可以递归地恢复其余字段
最后,会有类似于:
[0] = username,password
[1] = TB_PEOPLE.fields(FirstName,LastName,TB_PHONE.fields(num_phone1, num_phone2))
我希望我解释得更清楚一点,对不起。如果我正确理解了您的示例,您正在寻找以下内容:
[0] = a,b,c,
[1] = d.e(f,g,h,i.j(k,l))
[2] = m,n
(?<head>[a-zA-Z._]+\,)*(?<body>[a-zA-Z._]+[(].*[)])(?<tail>.*)
(?[a-zA-Z.\+\,)*(?[a-zA-Z.\+[(].[]))(?*)
对于给定字符串:
用户名、TB_PEOPLE.fields(名字、姓氏、TB_PHONE.fields(num_phone1、num_phone2))、密码
此表达式将匹配
- 用户名,用于组头
- TB\u人.字段(名字、姓氏、TB\u电话.字段(num\u phone1、num\u phone2))用于组body
- ,组尾部的密码
function parenthetical_depth(some_string):
open = count '(' in some_string
close = count ')' in some_string
return open - close
function smart_split(some_string):
bits = split some_string on ','
new_bits = empty list
bit = empty string
while bits has next:
bit = fetch next from bits
while parenthetical_depth(bit) != 0:
bit = bit + ',' + fetch next from bits
place bit into new_bits
return new_bits
这是最容易理解的方法,目前的算法是O(n^2)
-对内部循环进行了优化,使其O(n)
(字符串复制除外,这是其中最糟糕的部分):
通过巧妙地使用缓冲区和缓冲区大小,可以提高字符串复制的效率,但我认为C#无法在本地为您提供这种级别的控制。您可以使用以下方法:
(?>\w+\.)?\w+\((?>\((?<DEPTH>)|\)(?<-DEPTH>)|[^()]+)*\)(?(DEPTH)(?!))|\w+
说明:
(?>\w+\.)? \w+ \( # the opening parenthesis (with the function name)
(?> # open an atomic group
\( (?<DEPTH>) # when an opening parenthesis is encountered,
# then increment the stack named DEPTH
| # OR
\) (?<-DEPTH>) # when a closing parenthesis is encountered,
# then decrement the stack named DEPTH
| # OR
[^()]+ # content that is not parenthesis
)* # close the atomic group, repeat zero or more times
\) # the closing parenthesis
(?(DEPTH)(?!)) # conditional: if the stack named DEPTH is not empty
# then fail (ie: parenthesis are not balanced)
(?>\w+\)\w+\(#左括号(带函数名)
(?>#打开一个原子群
\(?)#当遇到左括号时,
#然后增加名为DEPTH的堆栈
|#或
\)(?)#遇到右括号时,
#然后递减名为DEPTH的堆栈
|#或
[^()]+#不是括号的内容
)*#关闭原子组,重复零次或多次
\)#右括号
(?(深度)(?!)#条件:如果名为DEPTH的堆栈不为空
#然后失败(即:括号不平衡)
您可以使用以下代码进行尝试:
string input = "username,TB_PEOPLE.fields(FirstName,LastName,TB_PHONE.fields(num_phone1, num_phone2)),password";
string pattern = @"(?>\w+\.)?\w+\((?>\((?<DEPTH>)|\)(?<-DEPTH>)|[^()]+)*\)(?(DEPTH)(?!))|\w+";
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
Console.WriteLine(match.Groups[0].Value);
}
string input=“用户名,TB_人.字段(名字,姓氏,TB_电话.字段(num_电话1,num_电话2)),密码”;
字符串模式=@“(?>\w+\)?\w+\(?>\((?)|\)(?)|[^()]+)*\(?(深度)(?!)|\w+”;
MatchCollection matches=Regex.matches(输入,模式);
foreach(匹配中的匹配)
{
Console.WriteLine(match.Groups[0].Value);
}
我不明白你的例子。不应该匹配[1]
是(f,g,h,I.j(k,l))
?如果没有,你能再解释一下吗?据我所知,正则表达式无法解析嵌套结构示例输入和输出没有意义。一个是(j,k)
,另一个是(k,l)
@casimirithippolyte:source或proof it…嗨!我正试图完全按照您所说的那样应用正则表达式,但我得到的回报是:[0]=>“[1]=>”、“[2]=>”、“,[3]=>”。您能告诉我忘记做什么吗?谢谢。您最好在原子组中使用嵌套的量化组,以防止回溯并加快对失败匹配的识别。例如,\((?>(?:\(?)|\)(?)|[^()]+)*)\
。但是,如果您不关心故障性能,那么就没有必要这样做。(此处的空格仅用于可读性)