很难解释我的意思,所以这就是我想做的事情
我想要按照
的模式解析任何句子text #something a few words [someothertext]
为此,匹配的句子将是
Jeremy is trying #20 times to [understand this]
我会将4个组命名为text,time,who,subtitle
但是,我也可以写
#20 Jeremy is trying [understand this] times to
仍然得到令牌 #20 杰里米正在努力 时间到 明白这个
对应于正确的群组
只要分隔的标记只能分隔2个文本标记,我就没事了。
这甚至可能吗?我已经尝试了一些正则表达式并且失败了(我还在尝试,但发现自己花了太多时间学习它)
注意:令牌的顺序可以是随机的。如果使用正则表达式无法做到这一点,那么我想我可以使用固定的顺序。
编辑:修正了错字。进一步澄清了我的想法。
答案 0 :(得分:2)
您可以替换不同类型的文字。使用命名组意味着每个匹配组的一个组的Success
值等于true。
这种模式可以满足您的需求:
@"(?<Number>#\d+\b)|(?<Subtitle>\[.+?])|\s*(?<Text>(?:.(?!#\d+\b|\[.*?]))+)\s*"
(?<Number>#\d+\b)
- 匹配#
后跟一个或多个数字,一直到字边界(?<Subtitle>\[.+?])
- 方括号内文字的非贪婪匹配\s*(?<Text>(?:.(?!#\d+\b|\[.*?]))+)\s*
- 修剪字符串两端的空格,并且指定的捕获组使用一次匹配单个字符的方法,前提是如果检测到文本会出现负面预测不匹配匹配其他2个感兴趣的文本模式(数字和副标题)。使用示例:
var inputs = new[]
{
"Jeremy is trying #20 times to [understand this]",
"#20 Jeremy is trying [understand this] times to"
};
string pattern = @"(?<Number>#\d+\b)|(?<Subtitle>\[.+?])|\s*(?<Text>(?:.(?!#\d+\b|\[.*?]))+)\s*";
foreach (var input in inputs)
{
Console.WriteLine("Input: " + input);
foreach (Match m in Regex.Matches(input, pattern))
{
// skip first group, which is the entire matched text
var group = m.Groups.Cast<Group>().Skip(1).First(g => g.Success);
Console.WriteLine(group.Value);
}
Console.WriteLine();
}
或者,此示例演示如何将命名组配对到匹配项:
var re = new Regex(pattern);
foreach (var input in inputs)
{
Console.WriteLine("Input: " + input);
var query = from Match m in re.Matches(input)
from g in re.GetGroupNames().Skip(1)
where m.Groups[g].Success
select new
{
GroupName = g,
Value = m.Groups[g].Value
};
foreach (var item in query)
{
Console.WriteLine("{0}: {1}", item.GroupName, item.Value);
}
Console.WriteLine();
}
答案 1 :(得分:0)
因此,如果我理解正确,你会找到四个短语:
1)正常文本的1+个字
2)1个以#为前缀的文字
3)正常文本的1+个字
4)由[]
我的(虽然速度慢且无正则表达式)建议是找到#,[和]字符的索引,然后使用几次调用string.Substring()。
对于相对较小的字符串和相对较少的迭代次数,这是可以接受的,尽管字符串要大得多,这将非常慢。