C# 函数/正则表达式以匹配较大字符串中的字符串部分&;突出部分

C# 函数/正则表达式以匹配较大字符串中的字符串部分&;突出部分,c#,regex,string,C#,Regex,String,我正在尝试构建一个函数,它接受一个搜索字符串,并匹配一个较大字符串中的部分&突出显示它们。见下例: 原始字符串:由于飞机头顶空间有限,我向您保证,托运行李将不收取任何费用,我可以继续为您填写所有托运行李表格 要搜索和突出显示的文本:不收费,我填写表格 理想结果:由于飞机头顶空间有限,我向您保证,托运行李不收取任何费用,我可以继续为您填写所有托运行李表格 我可以搜索完整的字符串,也可以使用子字符串一次搜索一个单词,但这两种方法都不会产生所需的结果。诀窍可能是以某种方式递归搜索,从完整字符串开始,然

我正在尝试构建一个函数,它接受一个搜索字符串,并匹配一个较大字符串中的部分&突出显示它们。见下例:

原始字符串:由于飞机头顶空间有限,我向您保证,托运行李将不收取任何费用,我可以继续为您填写所有托运行李表格

要搜索和突出显示的文本:不收费,我填写表格

理想结果:由于飞机头顶空间有限,我向您保证,托运行李不收取任何费用,我可以继续为您填写所有托运行李表格

我可以搜索完整的字符串,也可以使用子字符串一次搜索一个单词,但这两种方法都不会产生所需的结果。诀窍可能是以某种方式递归搜索,从完整字符串开始,然后逐渐将其分解为更小的部分,直到部分匹配为止。有两个假设:

  • 搜索必须尽可能贪婪,即在尝试匹配较小部分或单个单词之前匹配字符串的较大部分
  • 在找到任何匹配项后,搜索将始终向前进行,即如果在位置x处找到前2个单词,则单词3和4将始终位于x之后,而不是x之前
希望这是有道理的。谁能给我指出正确的方向吗?我已经搜索了这个网站,但没有找到任何与我正在寻找的类似的东西


谢谢

如果这对您有帮助,请告诉我。它不使用正则表达式来查找字符串,只需
IndexOf

它首先将要突出显示的单词作为
Tuple
,表示单词的开始索引和结束索引

它使用环绕单词的前缀和后缀(此处:html标记)高亮显示文本

static void Main(字符串[]args)
{
var input=“由于飞机头顶空间有限,我向您保证,托运行李将不收取任何费用,我可以继续为您填写所有托运行李表格”;
var searchExpression=“不收费,我填写表格”;
var highlightedInput=HighlightString(输入,搜索表达式,“,”);
控制台写入线(高亮显示输入);
Console.ReadLine();
}
公共静态IEnumerable GetHighlights(字符串输入、字符串搜索表达式)
{
var splitintoordsregex=新正则表达式(@“\W+”);
var words=splitintoordsregex.Split(searchExpression);
返回GetHighlights(输入,单词);
}
公共静态IEnumerable GetHighlights(字符串输入,IEnumerable搜索表达式)
{
var highlights=新列表();
var lastMatchedIndex=0;
foreach(searchExpression中的var单词)
{
var indexoford=input.IndexOf(word、lastMatchedIndex、StringComparison.CurrentCulture);
var lastIndexOfWord=indexOfWord+字长;
添加(新元组(indexoford,lastIndexoford));
lastMatchedIndex=lastIndexOfWord;
}
回归亮点;
}
公共静态字符串HighlightString(字符串输入、字符串搜索表达式、字符串highlightPrefix、字符串highlightSufix)
{
var highlights=GetHighlights(输入,searchExpression).ToList();
var输出=输入;
for(inti=0,j=highlights.Count;i新元组(word,index,index+word.Length));
}
//缩小高光的范围,以便
//尽可能将索引保持在一起。
var firstWord=searchExpression.First();
var firstWordIndex=highlights.IndexOf(highlights.Last(x=>String.Equals(x.Item1,firstWord));
var lastWord=searchExpression.Last();
var lastWordIndex=highlights.IndexOf(highlights.Last(x=>String.Equals(x.Item1,lastWord));
var sanitizedHighlights=highlights.SkipWhile((x,i)=>ii String.Equals(x.Item1,word));
sanitizedHighlights=sanitizedHighlights.TakeWhile(x=>x.Item3newtuple(x.Item2,x.Item3));
}
公共静态列表AllIndexesOf(字符串str、字符串值、字符串比较)
{
if(String.IsNullOrEmpty(value))
抛出新ArgumentException(“要查找的字符串可能不为空”、“值”);
列表索引=新列表();
for(int index=0;index+=value.Length)
{
索引=str.IndexOf(值、索引、比较);
如果(索引==-1)
收益指标;
索引。添加(索引);
}
}
使用此代码和文本:

“不,关于费用,由于飞机头顶空间有限,我向您保证,托运行李将不收费,我可以继续为您填写所有托运行李表格。”

我得到了以下结果:

不,关于费用,由于飞机头顶空间有限,我向你保证,托运行李将不收费,我可以继续为你填写所有托运行李表格

======================================================

编辑2使用正则表达式方法,结合之前尝试获得的经验
请注意,如果没有找到表达式中的每个单词,则不会找到突出显示

public static IEnumerable<Tuple<int,int>> GetHighlights(string expression, string search)
{
    var highlights = new List<Tuple<string, int, int>>();

    var wordsToHighlight = new Regex(@"(\w+|[^\s]+)").
        Matches(search).
        Cast<Match>().
        Select(x => x.Value);

    foreach(var wordToHighlight in wordsToHighlight)
    {
        Regex findMatchRegex = null;
        if (new Regex(@"\W").IsMatch(wordToHighlight))
            findMatchRegex = new Regex(String.Format(@"({0})", wordToHighlight), RegexOptions.IgnoreCase);  // is punctuation
        else
            findMatchRegex = new Regex(String.Format(@"((?<!\w){0}(?!\w))", wordToHighlight), RegexOptions.IgnoreCase); // si word

        var matches = findMatchRegex.Matches(expression).Cast<Match>().Select(match => new Tuple<string, int, int>(wordToHighlight, match.Index, match.Index + wordToHighlight.Length));

        if (matches.Any())
            highlights.AddRange(matches);
        else
            return new List<Tuple<int, int>>();
    }

    // Reduce the scope of the highlights in order to 
    // keep the indexes as together as possible.
    var firstWord = wordsToHighlight.First();
    var firstWordIndex = highlights.IndexOf(highlights.Last(x => String.Equals(x.Item1, firstWord)));

    var lastWord = wordsToHighlight.Last();
    var lastWordIndex = highlights.IndexOf(highlights.Last(x => String.Equals(x.Item1, lastWord)));

    var sanitizedHighlights = highlights.SkipWhile((x, i) => i < firstWordIndex);
    sanitizedHighlights = sanitizedHighlights.TakeWhile((x, i) => i <= lastWordIndex);

    highlights = new List<Tuple<string, int, int>>();
    foreach (var word in wordsToHighlight.Reverse())
    {
        var lastOccurence = sanitizedHighlights.Last((x) => String.Equals(x.Item1, word));
        sanitizedHighlights = sanitizedHighlights.TakeWhile(x => x.Item3 < lastOccurence.Item2);
        highlights.Add(lastOccurence);
    }

    highlights.Reverse();

    return highlights.Select(x => new Tuple<int, int>(x.Item2, x.Item3));
}
公共静态IEnumerable GetHighlights(字符串表达式、字符串搜索)
{
var highlights=新列表();
var wordsToHighlight=new Regex(@“(\w+|[^\s]+)”)。
匹配(搜索)。
Cast()。
选择(x=>x.Value);
foreach(wordsToHighlight中的var wordToHighlight)
{
Regex findMatchRegex=null;
if(新正则表达式(@“\W”).IsMatch(wordToHighlight))
findMatchRegex=newregex(String.Format(@“({0})”,wordToHighlight),RegexOptions.IgnoreCase);//是标点符号
其他的