【问题标题】:.NET Regex overlaping matches taking last character.NET 正则表达式重叠匹配取最后一个字符
【发布时间】:2016-01-11 10:50:55
【问题描述】:

我有这个正则表达式,它可以找到一个 A、一个 B 和两个 C 的任何排列

(?:(?<A>A)|(?<B>B)|(?<C>C)){4}(?<-A>)(?<-B>)(?<-C>){2}

例如,对于这个组合,我们有 3 个匹配项(位置 1、7、15)

ABCCABCABCABCAABCC

如果我添加一个前瞻断言,我可以计算从下一个位置开始的巧合数,而不是完整序列之后的下一个位置

(?=(?<value>(?:(?<A>A)|(?<B>B)|(?<C>C)){4}(?<-A>)(?<-B>)(?<-C>){2}))
   ^                                                               ^

在这个例子中我们有 7 个匹配项

1. ABCC
2. BCCA
3. CCAB
4. CABC
7. CABC
10. CABC
15. ABCC

正如 stribizhev 在上一篇文章中提供的帮助: .NET Regex number of overlaping matches

现在我需要找到所有可能组合的序列,例如 ABC,但 3 次并重叠一个字符。

例如,对于以下序列:

AABCBACBCCAACCB

这将具有位置 1 的序列

Pos 1. ABC
Pos 3. CBA
Pos 5. ACB

所以它看起来是一个序列,其中我们有连续出现 3 次的任意 ABC 组合,但将前一个匹配的最后一个字符作为第一个字符。

希望我解释清楚..

我该怎么做?

【问题讨论】:

  • 您需要使用正则表达式吗?即使有可能,我怀疑遍历字符串并计算相关字符会更快、更清晰。
  • @sln 看起来 OP 在最后一个示例中使用基于零的 Pos
  • @PetSerAl - 没错,我要失明了。
  • 如果只有 2 次“几乎连续”出现怎么办?你用什么语言写的? C#?只是正则表达式无济于事。您需要职位详情吗?

标签: .net regex


【解决方案1】:

您可以通过对@stribizhev 解决方案的简单修改来实现这一点。

首先,你只有C 而不是两个:

(?:(?<A>A)|(?<B>B)|(?<C>C)){3}(?<-A>)(?<-B>)(?<-C>)

由于您想从最后一个字符开始新的匹配,您可以使用前瞻断言并仅捕获其后的两个字符:

(?=(?:(?<A>A)|(?<B>B)|(?<C>C)){3}(?<-A>)(?<-B>)(?<-C>))..

现在你只需重复 3 次,然后只捕获最后一个字符:

(?:(?=(?:(?<A>A)|(?<B>B)|(?<C>C)){3}(?<-A>)(?<-B>)(?<-C>))..){3}.

【讨论】:

  • 感谢您的回答。我想我们正在接近。我已经编辑了我的问题,因为我认为我没有很好地解释。
  • 我想当模式中有 4 个字符(如 ABCC)或重复 4 次而不是 3 次时,情况会相似,但我无法弄清楚公式...
  • @MikeJohnson 假设你有REGEX,它匹配四个字符并且你想要四个重复:(?:(?=REGEX).{3}){4}.。第一个{?} 是字符数减一,第二个{?} 是重复次数。
【解决方案2】:

以下是在 C# 中实现这一点的方法 - 请注意,s 变量将在整个过程中被修改,因此请先克隆它或使用副本:

var s = "AABCBACBCCAACCB AABCBACBCCAACCB AABBBAABCCAACCB";
var rx = new Regex("(?=(?<value>(?:(?<A>A)|(?<B>B)|(?<C>C)){3}(?<-A>)(?<-B>)(?<-C>)))");
var m = rx.Match(s);
while (m.Success)
{
    var list = new List<string>();
    list.Add(m.Groups["value"].Value);
    s = s.Substring(m.Groups["value"].Index+m.Groups["value"].Length-1);
    m = rx.Match(s);
    if (m.Success && m.Groups["value"].Index == 0)
    {
        list.Add(m.Groups["value"].Value);
        s = s.Substring(m.Groups["value"].Index+m.Groups["value"].Length-1);
        m = rx.Match(s);
        if (m.Success && m.Groups["value"].Index == 0)
        {
            list.Add(m.Groups["value"].Value);
            Console.WriteLine(string.Join(", ", list));
            s = s.Sustring(m.Groups["value"].Index+m.Groups["value"].Length-1);
            m = rx.Match(s);
        }
    }
}

IDEONE demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 2016-10-24
    相关资源
    最近更新 更多