命名组分裂,无论匹配位置如何

时间:2012-03-24 22:58:41

标签: c# regex

很难解释我的意思,所以这就是我想做的事情

我想要按照

的模式解析任何句子
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个文本标记,我就没事了。

这甚至可能吗?我已经尝试了一些正则表达式并且失败了(我还在尝试,但发现自己花了太多时间学习它)

注意:令牌的顺序可以是随机的。如果使用正则表达式无法做到这一点,那么我想我可以使用固定的顺序。

编辑:修正了错字。进一步澄清了我的想法。

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)由[]

包装的1+个文字

我的(虽然速度慢且无正则表达式)建议是找到#,[和]字符的索引,然后使用几次调用string.Substring()。

对于相对较小的字符串和相对较少的迭代次数,这是可以接受的,尽管字符串要大得多,这将非常慢。