我有这种形式的一些数据:
@"Managers Alice, Bob, Charlie
Supervisors Don, Edward, Francis"
我需要像这样的扁平输出:
@"Managers Alice
Managers Bob
Managers Charlie
Supervisors Don
Supervisors Edward
Supervisors Francis"
上面的实际“职称”可以是任何一个单词,也没有可以使用的离散列表。
将,
替换为\r\n
非常容易,第一次替换也是如此:
Replace (^|\r\n)(\S+\s)([^,\r\n]*),\s
With $1$2$3\r\n$2
但是捕获其他名称并应用相同的前缀是我今天无法想象的。有什么建议吗?
我正在寻找一系列一个或多个RegEx.Replace()
调用,在C#中没有任何LINQ或过程代码,这当然是微不足道的。实现不是直接的在C#代码中,我正在配置一个通用的解析工具,该工具使用一系列.NET正则表达式来转换来自各种来源的传入数据,以用于多种用途。
答案 0 :(得分:1)
这是一个纯粹的替换解决方案:
string s = @"Managers Alice, Bob, Charlie
Supervisors Don, Edward, Francis";
Regex r = new Regex(@"(?:^\w+)?( \w+)(?<=^(\w+)\b.*)[,\r\n]*",
RegexOptions.Multiline);
string s1 = r.Replace(s0, "$2$1\r\n");
在匹配每个名称后,lookbehind返回到当前行的开头以捕获标题。 (?:^\w+)?
和[,\r\n]*
仅用于消耗您不想保留的字符串部分。
答案 1 :(得分:0)
为什么要使用正则表达式,如果你可以使用LINQ?
string s = "Managers Alice, Bob, Charlie\r\nSupervisors Don, Edward, Francis";
var result =
from line in s.Split(new string[] { "\r\n" }, StringSplitOptions.None)
let parts = line.Split(new char[] { ' ' }, 2)
let title = parts[0]
let names = parts[1]
from name in names.Split(new char[] { ',' })
select title.Trim() + " " + name.Trim();
string.Join("\r\n", result)
是
Managers Alice Managers Bob Managers Charlie Supervisors Don Supervisors Edward Supervisors Francis
答案 2 :(得分:0)
既然你强调了正则表达式的必要性,那么这个解决方案应该适合你。
string input = @"Managers Alice, Bob, Charlie
Supervisors Don, Edward, Francis";
string pattern = @"(?<Title>\w+)\s+(?:(?<Names>\w+)(?:,\s+)?)+";
foreach (Match m in Regex.Matches(input, pattern))
{
Console.WriteLine("Title: {0}", m.Groups["Title"].Value);
foreach (Capture c in m.Groups["Names"].Captures)
{
Console.WriteLine(c.Value);
}
Console.WriteLine();
}
主要概念是使用命名的“标题”组来存储作业标题并在以后引用它们。名称存储在捕获集合中。只有在数据格式正确的情况下才能使用该模式,如样本数据中所示。
模式细分如下:(?<Title>\w+)\s+(?:(?<Names>\w+)(?:,\s+)?)+
(?<Title>\w+)\s+
- 匹配第一个空格之前的标题,并将其放入指定的Title
组中。必须至少有一个空格。Names
部分存储在(?<Names>\w+)
组中,逗号和至少一个空格通过(?:...)
部分匹配(但未使用(?:,\s+)?
后未捕获)并且它是可选的,因为?
位于其后面。最后,模式的整个部分被包含在一个必须至少匹配一次(?:...)+
的组中,但由于我们只捕获了我们感兴趣的部分,因此不会被捕获。答案 3 :(得分:0)
您可以搜索
^(\w+)[ \t]+(\w+),[ \t]+(.+)$
并将所有内容替换为
\1 \2\r\n\1 \3
您需要将两次应用于您的示例,如果经理列表增长到四,则需要三次等等。
所以,在C#中:
resultString = Regex.Replace(subjectString, @"^(\w+)[ \t]+(\w+),[ \t]+(.+)$", @"$1 $2\r\n$1 $3", RegexOptions.Multiline);
说明:
^
:匹配行的开头
(\w+)[ \t]+
:匹配任意数量的alnum字符,捕获匹配项;匹配以下空格
(\w+)
:匹配下一个“字”,然后
,[ \t]+(.+)$
匹配一个逗号,空格,然后是后续的任何内容,直到该行的结尾。只有当该行仍包含需要拆分的内容时,才会匹配。