有没有办法指定正则表达式来匹配字符串中每个第二次出现的模式?
实施例
答案 0 :(得分:54)
使用分组。
foo.*?(foo)
答案 1 :(得分:9)
假设您想要的模式是abc + d。您希望在字符串中匹配此模式的第二次出现。
您将构建以下正则表达式:
abc+d.*?(abc+d)
这将匹配表单的字符串:<your-pattern>...<your-pattern>
。既然我们正在使用不情愿的限定符*?我们很安全,两者之间不可能有另一场比赛。使用几乎所有正则表达式实现提供的匹配器组,然后将在括号内的组中检索您想要的字符串。
答案 2 :(得分:6)
如果你正在使用C#,你可以一次获得所有匹配(即使用Regex.Matches()
,返回MatchCollection
,并检查项目的索引:index % 2 != 0
)。
如果要查找替换它的匹配项,请使用Regex.Replace()
的一个重载使用MatchEvaluator
(例如Regex.Replace(String, String, 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;
}
}
}
}
答案 3 :(得分:2)
会像
(pattern.*?(pattern))*
为你工作?
编辑:
这个问题在于它使用非贪婪的运算符*?
,这可能需要沿着字符串进行大量的回溯,而不是只查看每个字母一次。这对你意味着什么,这对于大的差距来说可能是缓慢的。
答案 4 :(得分:2)
返回引用可以在这里找到有趣的解决方案。这个正则表达式:
([a-z]+).*(\1)
将找到最长的重复序列。
这个将找到重复的3个字母的序列:
([a-z]{3}).*(\1)
答案 5 :(得分:0)
没有“直接”的方式,但您可以指定模式两次:a[^a]*a
匹配第二个“a”。
另一种方法是使用您的编程语言(perl?C#?...)来匹配第一次出现,然后是第二次出现。
编辑:我看到其他人使用“非贪婪”操作符进行了回复,这可能是一个很好的方法,假设你在你的正则表达式库中有它们!