【问题标题】:Match regex at exact offset在精确偏移处匹配正则表达式
【发布时间】:2011-02-13 10:49:44
【问题描述】:

我想检查某个模式(例如双引号字符串)是否在确切位置匹配。

示例

string text = "aaabbb";
Regex regex = new Regex("b+");
// Now match regex at exactly char 3 (offset) of text

我想检查 regex 是否与字符 3 完全匹配。
我查看了Regex.Match Method (String, Int32),但它的行为不像我预期的那样。
所以我做了一些测试和一些解决方法:

public void RegexTest2()
{
    Match m;
    string text = "aaabbb";
    int offset = 3;

    m = new Regex("^a+").Match(text, 0); // lets do a sanity check first
    Assert.AreEqual(true, m.Success);
    Assert.AreEqual("aaa", m.Value);  // works as expected

    m = new Regex("^b+").Match(text, offset);
    Assert.AreEqual(false, m.Success);  // this is quite strange...

    m = new Regex("^.{"+offset+"}(b+)").Match(text); // works, but is not very 'nice'
    Assert.AreEqual(true, m.Success);
    Assert.AreEqual("bbb", m.Groups[1].Value);

    m = new Regex("^b+").Match(text.Substring(offset)); // works too, but 
    Assert.AreEqual(true, m.Success);
    Assert.AreEqual("bbb", m.Value);
}

事实上,我开始相信new Regex("^.", 1).Match(myString)永远不会匹配任何东西。

有什么建议吗?

编辑:

我有一个可行的解决方案(workaround)。所以我的问题都是关于速度和一个好的实现。

【问题讨论】:

    标签: c# .net regex


    【解决方案1】:

    你试过docs说什么吗?

    如果你想限制匹配,那么 它始于一个特定的 字符串中的字符位置和 正则表达式引擎不 扫描字符串的其余部分以查找 匹配,锚定正则表达式 带有 \G (在左侧为 从左到右的模式,或在右边 对于从右到左的模式)。这 限制比赛,所以它必须开始 正好在 startat。

    即将^ 替换为\G

    m = new Regex(@"\\Gb+").Match(text, offset);
    Assert.AreEqual(true, m.Success);  // should now work
    

    【讨论】:

    • 比我快 8 秒,我花了太长时间才确认 :P\G 在这里是正确的,但我会添加一个关于使用相同 Regex 对象的警告,假设 OP 不会每次都创建一个新对象。我不太确定它会如何表现,但它可能会记住最后一个位置,即使有偏移量。值得检查一下。 (再次,我不确定)
    • @Kobi - 我怀疑只有在使用 m.MatchNext() 时才会出现这种情况,而不是在同一个 Regex 对象上再次调用 Match() 时。
    • @CAFxX:应该是@"\Gb+""\\Gb+"
    • 我确实读过 msdn.microsoft.com/en-us/library/az24scfc.aspx : The match must occur at the point where the previous match ended.这并没有说服我去尝试。非常感谢!
    【解决方案2】:

    您希望Match(text, offset) 开始评估搜索的字符串,就好像它从偏移量开始一样。事实并非如此。 ^ 实际上将评估为抵消 0,而不是 offset

    所以使用overload of Match^ 评估为offset

    m = new Regex("^bbb$").Match(text, offset, text.Length-offset);
    

    另一种选择是使用,但它比上面的慢:

    m = new Regex("^.{"+offset+"}bbb$").Match(text);
    

    或者这个(第一种方法最快):

    m = new Regex(@"\Gbbb$").Match(text, offset);
    

    【讨论】:

      【解决方案3】:

      您可以在您的正则表达式中添加一个肯定的后向断言 ((?<=...)):

      Regex regex = new Regex("(?<=\A.{3})b+");
      

      这可确保在字符串 (\A) 开始之后和正则表达式开始之前正好有三个字符 (.{3})。您也可以使用^ 代替\A,但由于前者也可以表示(在某些情况下)“在行首匹配”,因此后者更加明确。

      如果需要,您可能需要使用 RegexOptions.Singleline 编译正则表达式以允许点也匹配换行符。

      顺便说一句,

      m = new Regex("^b+").Match(text, 3);
      

      不起作用,因为^ 匹配行首,而第一个b 之前的位置当然不在行首。

      【讨论】:

      • 对不起,我忘了说,'3' 的偏移量是一个变量。如果我为每个调用构建一个新的正则表达式,它会不会显着降低性能?
      • 好吧,在这种情况下,我提倡使用Substring 来首先获取字符串的相关部分,然后在其余部分释放正则表达式的愤怒。
      • 如果要匹配的字符串很长,那不是很慢吗?
      猜你喜欢
      • 2012-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      • 2011-08-10
      相关资源
      最近更新 更多