C# 如何使用Regex.Split获取组名
我正在研究可能在括号之间包含内容的字符串,例如:C# 如何使用Regex.Split获取组名,c#,regex,C#,Regex,我正在研究可能在括号之间包含内容的字符串,例如: "Hello World" "(Hello) World" "(Hello World)" "(Hello) (World)" "bla bla (Hello World) bla bla" "Hello (World" 为此我编写了这个简单的正则表达式:\(.*): 但是,我需要对括号之间捕获的部分进行特殊处理 我认为使用命名组,例如(?*?)\(?*?)(?*?),但是使用组需要使用Match()和GetGroupNames()等方法,我得
"Hello World"
"(Hello) World"
"(Hello World)"
"(Hello) (World)"
"bla bla (Hello World) bla bla"
"Hello (World"
为此我编写了这个简单的正则表达式:\(.*)
:
但是,我需要对括号之间捕获的部分进行特殊处理
我认为使用命名组,例如(?*?)\(?*?)(?*?)
,但是使用组需要使用Match()
和GetGroupNames()
等方法,我得到了错误的结果:
// Inputs are the same than above
foreach (var input in Inputs)
{
var rgx = new Regex(@"(?<others1>.*?)\((?<choice>.*?)\)(?<others2>.*?)");
var matches = rgx.Matches(input);
var groups = rgx.GetGroupNames();
Console.WriteLine($"Input : {input}");
foreach (Match match in matches)
{
foreach (var group in groups)
{
Group grp = match.Groups[group];
Console.WriteLine(" {0}: '{1}'", group, grp.Value);
// if (group == "choice")
// SpecialTreatment(grp.Value);
}
}
Console.WriteLine("--------------------------------");
}
是否有一种方法可以使组名受益于
Regex.Split()
?您可以使用稍微不同的Regex来保留括号:
var parts = Regex.Split(input, @"(\(.*?\))");
问题中的一个例子应报告:
Input : (Hello) World
> ''
> '(Hello)'
> ' World'
然后,只需检查部分
中每个元素的第一个和最后一个字符的括号
另一种办法是:
var parts = Regex.Split(input, @"([()])");
这将产生:
Input : (Hello) World
> ''
> '('
> 'Hello'
> ')'
> ' World'
这也清楚地显示了括号内的文本。坦率地说,这个问题已经遍布整个地图。您是想要最终结果还是想要修复流程中的一个步骤?作为一名程序员的一部分是把事情分解成几个小步骤,并在每个步骤上工作。你还没有这么做…所以让我们这样做:
看一下,这个问题的答案可以使用regex来完成,但是必须使用在匹配中找到的捕获组来正确地分离项目。一旦它们被分离,那么你就可以获取目标项,它是一个索引,在每次匹配后都会增加 示例
xxx (abc|def|ghi) yyy (ijk|lmn|opq) zzz
最终结果
xxx abc yyy lmn zzz
Match #0
[0]: xxx
["Grouped"] → [1]:
["NotGrouped"] → [2]: xxx
→2 Captures: xxx
Match #1
[0]: (abc | def | ghi)
["Grouped"] → [1]: ghi
→1 Captures: abc, def, ghi
["NotGrouped"] → [2]:
Match #2
[0]: yyy
["Grouped"] → [1]:
["NotGrouped"] → [2]: yyy
→2 Captures: yyy
Match #3
[0]: (ijk | lmn | opq)
["Grouped"] → [1]: opq
→1 Captures: ijk, lmn, opq
["NotGrouped"] → [2]:
Match #4
[0]: zzz
["Grouped"] → [1]:
["NotGrouped"] → [2]: zzz
→2 Captures: zzz
模式
下面是模式,请注释以进行解释。此正则表达式查找组或非组。从组内,它将单独的文本添加到内部捕获数组中:
var pattern = @" # Either its in a Group
\( #(literal paren start)
(
(?<Grouped>[^|(]+) # Match up to the pipe or paren
\|? # Don't match the pipe but consume it if there
)+ # One to many of these piped items
\) # (literal paren stop)
| # Or its not in a group
(?<NotGrouped>[^(]+) #
";
因此,如果分组是非管道的
,我们将忽略捕获(因为只有一个)与匹配本身的棍子。如果它是其中一个数据组,我们将重点关注捕获
C#解决方案
int index = 0;
string.Join(string.Empty,
Regex.Matches(text, pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture)
.OfType<Match>()
.Select(mtch => mtch.Groups["NotGrouped"].Success ? mtch.Groups["NotGrouped"].Value
: mtch.Groups["Grouped"].Captures
.OfType<Capture>()
.Select(cpt => cpt.Value)
.ToList()[index++]
)
)
int索引=0;
Join(string.Empty,
Regex.Matches(文本、模式、RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture)
第()类
.Select(mtch=>mtch.Groups[“NotGrouped”]。成功?mtch.Groups[“NotGrouped”]。值
:mtch.Groups[“Grouped”]。捕获
第()类
.Select(cpt=>cpt.Value)
.ToList()[index++]
)
)
结果是模式末尾的xxx abc yyy lmn zzz
*?
从不匹配任何字符。为什么需要命名组?您不需要它们,这是一个XY问题。请解释你最终需要达到的目标。那么,你有了bla-bla(Hello World)bla-bla
,你到底需要得到什么?@WiktorStribiżew我刚刚弄明白为什么*?
在最后是无用的,这是惰性匹配,空字符串将匹配。我需要应用一个String.Split()
,然后对(…)
进行一些只匹配的计算,这就是为什么我认为使用名称可以帮助我识别这些部分。对于bla bla bla(Hello World)bla bla
,我需要检索()
之前、之后和内部的部分,因此,您的代码可以工作。为什么要改变它?为什么要问一个问题?是的,这个问题被很多人误解了。另外,你并不真的需要你描述的检查,你可以使用我的方法。看,这几乎是这个问题的一个愚蠢的理由。
var pattern = @" # Either its in a Group
\( #(literal paren start)
(
(?<Grouped>[^|(]+) # Match up to the pipe or paren
\|? # Don't match the pipe but consume it if there
)+ # One to many of these piped items
\) # (literal paren stop)
| # Or its not in a group
(?<NotGrouped>[^(]+) #
";
Match #0
[0]: xxx
["Grouped"] → [1]:
["NotGrouped"] → [2]: xxx
→2 Captures: xxx
Match #1
[0]: (abc | def | ghi)
["Grouped"] → [1]: ghi
→1 Captures: abc, def, ghi
["NotGrouped"] → [2]:
Match #2
[0]: yyy
["Grouped"] → [1]:
["NotGrouped"] → [2]: yyy
→2 Captures: yyy
Match #3
[0]: (ijk | lmn | opq)
["Grouped"] → [1]: opq
→1 Captures: ijk, lmn, opq
["NotGrouped"] → [2]:
Match #4
[0]: zzz
["Grouped"] → [1]:
["NotGrouped"] → [2]: zzz
→2 Captures: zzz
int index = 0;
string.Join(string.Empty,
Regex.Matches(text, pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture)
.OfType<Match>()
.Select(mtch => mtch.Groups["NotGrouped"].Success ? mtch.Groups["NotGrouped"].Value
: mtch.Groups["Grouped"].Captures
.OfType<Capture>()
.Select(cpt => cpt.Value)
.ToList()[index++]
)
)