2009-02-26 52 views
27

有沒有一種方法可以指定一個正則表達式來匹配字符串中每個第2次出現的模式?每隔一次匹配

例子

  • 搜索一個對字符串abcdabcd應該找到第5位
  • 對字符串搜索AB一個發生abcdabcd應該找到位置出現一次5
  • 正在搜索dab針對字符串abcdabcd應該找到沒有出現
  • 搜索一個對字符串AAAA應該找兩個出現在位置2和4
+1

也許我太挑剔,但一個正則表達式不會「找到」任何東西。它只會「匹配」你輸入字符串的一部分。這是您的編程語言,它爲您提供了將字符串與正則表達式匹配並返回有關匹配的各種信息(例如,它發生的位置)的功能。 – 2009-02-26 09:35:12

+16

你是對的,你太挑剔;) – 2013-08-09 14:25:04

回答

46

使用分組。

foo.*?(foo) 
2

會像你

(pattern.\*?(pattern))* 

工作?

編輯:

這樣做的問題是使用非貪婪操作符*?它可以是需要非常多沿串回溯的,而正則表達式通常沒有看一封信不止一次。這對你意味着什麼,這可能會導致大的差距。

+0

需要非貪婪 – annakata 2009-02-26 08:52:32

+0

忘了這一點。修復。 – Patrick 2009-02-26 08:53:58

8

假設你想要的模式是abc + d。你想在字符串中匹配這個模式的第二次出現。

您將構建以下的正則表達式:

abc+d.*?(abc+d) 

這將匹配形式的字符串:<your-pattern>...<your-pattern>。因爲我們使用了不情願的限定詞*?我們很安全,兩者之間不可能有其他匹配。使用幾乎所有的正則表達式實現提供給你的matcher組將會檢索出你想要的括號內的字符串。

0

有這樣的沒有「直接」的方式,但你可以在指定兩次模式:a[^a]*a匹配到第二個「一」是。

另一種方法是使用您的編程語言(perl?C#?...)來匹配第一個匹配項,然後匹配第二個匹配項。

編輯:我見過其他使用「非貪婪」運營商可能是一個很好的路要走回應,假設你有他們在你的正則表達式庫!

6

如果您使用的是C#,您可以一次獲得所有匹配,即。使用返回MatchCollection的Regex.Matches()(檢查項目的索引,索引%2!= 0)。

如果您想查找發生的事件來替換它,請使用Regex.Replace()中使用MatchEvaluator的重載之一)。 Regex.Replace(字符串,字符串,MatchEvaluator,下面的代碼:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Text.RegularExpressions; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string input = "abcdabcd"; 

      // Replace *second* a with m 

      string replacedString = Regex.Replace(
       input, 
       "a", 
       new SecondOccuranceFinder("m").MatchEvaluator); 

      Console.WriteLine(replacedString); 
      Console.Read(); 

     } 

     class SecondOccuranceFinder 
     { 
      public SecondOccuranceFinder(string replaceWith) 
      { 
       _replaceWith = replaceWith; 
       _matchEvaluator = new MatchEvaluator(IsSecondOccurance); 
      } 

      private string _replaceWith; 

      private MatchEvaluator _matchEvaluator; 
      public MatchEvaluator MatchEvaluator 
      { 
       get 
       { 
        return _matchEvaluator; 
       } 
      } 

      private int _matchIndex; 
      public string IsSecondOccurance(Match m) 
      { 
       _matchIndex++; 
       if (_matchIndex % 2 == 0) 
        return _replaceWith; 
       else 
        return m.Value; 
      } 
     } 
    } 
} 
2

返回引用可以在這裏找到有趣的解決方案此正則表達式:

([a-z]+).*(\1) 

會發現最長的重複序列

。這一個會發現一個重複的3個字母的序列:

([a-z]{3}).*(\1)