C# 术语表函数的正则表达式

C# 术语表函数的正则表达式,c#,.net,regex,C#,.net,Regex,我正在开发一个基于web的帮助系统,该系统将自动在解释文本中插入链接,将用户带到帮助中的其他主题。我有数百个应该链接的术语,即 “手册和标签”(一般描述这些概念) “删除手册和标签”(描述此特定操作) “了解有关添加手册和标签的更多信息”(同样,更具体的操作) 我有一个正则表达式来查找/替换整个单词(good ol'\b),除了在其他链接术语中找到的链接术语外,它非常有效。而不是: <a href="#">Learn more about manuals and labels<

我正在开发一个基于web的帮助系统,该系统将自动在解释文本中插入链接,将用户带到帮助中的其他主题。我有数百个应该链接的术语,即

“手册和标签”(一般描述这些概念) “删除手册和标签”(描述此特定操作) “了解有关添加手册和标签的更多信息”(同样,更具体的操作)

我有一个正则表达式来查找/替换整个单词(good ol'\b),除了在其他链接术语中找到的链接术语外,它非常有效。而不是:

<a href="#">Learn more about manuals and labels</a>

我最终得到了

<a href="#">Learn more about <a href="#">manuals and labels</a></a>

这让每个人都有点哭。更改术语的替换顺序(从最短到最长)意味着我将得到:

了解更多关于
没有我真正需要的外部链接

更复杂的是,搜索词的大小写可能会有所不同,我需要保留原来的大小写。如果我能做这样的事,我会准备好的:

Regex _regex = new Regex("\\b" + termToFind + "(|s)" + "\\b", RegexOptions.IgnoreCase);

string resultingText = _regex.Replace(textThatNeedsLinksInserted, "<a>" + "$&".Replace(" ", "_") + "</a>));
Regex\u Regex=new Regex(\\b“+termToFind+”(|s“+”\\b),RegexOptions.IgnoreCase);
字符串结果文本=_regex.Replace(需要链接的文本插入“+”$&.Replace(“,“”)+”);
然后在所有条款完成后,删除“u”,这将是完美的。“了解更多关于手册和标签”将与“手册和标签”不匹配,一切都很好

在编写文本时,很难让帮助作者定义需要替换的术语,因为他们不习惯编码。此外,这将限制以后添加新术语的灵活性,因为我们必须返回并向以前编写的所有文本添加分隔符


是否有一个正则表达式可以让我在原始匹配中用“ux”替换空白?或者是否有另一个解决方案让我无法理解?

首先,您可以使用一个正则表达式阻止您的
手册和标签的正则表达式查找
了解更多关于手册和标签的信息。修改后的正则表达式如下所示:

(?<!Learn more about )(manuals and labels)
(?
但对于您的特定请求,我建议使用不同的解决方案。您应该为您的正则表达式或两者定义一个规则或优先级列表。可能的规则是“始终首先搜索匹配最多字符的正则表达式”“。但是,这要求您的正则表达式始终是固定长度的。这并不能阻止一个正则表达式使用和替换本应由不同正则表达式(甚至可能是相同大小)匹配的字符


当然,您需要为每个Regex添加额外的lookbehind和lookbeahead,以防止用嵌套链接替换示例中替换元素内部的字符串。这听起来像是在对术语进行单独传递,并执行多个
Regex.Replace
调用g一个正则表达式,你应该让它做繁重的工作,并把一个很好的模式放在一起,利用交替

换句话说,您可能需要这样的模式:
\b(term1 | term2 | termN)\b


我会使用这样的有序字典,确保最小的术语是最后一个:

using System;
using System.Text.RegularExpressions;
using System.Collections.Specialized;

public class Test
{
    public static void Main()
    {
        OrderedDictionary Links = new OrderedDictionary();
        Links.Add("Learn more about adding manuals and labels", "2");
        Links.Add("Delete Manuals and Labels", "3");
        Links.Add("manuals and labels", "1");

        string text = "Having trouble with your manuals and labels? Learn more about adding manuals and labels. Need to get rid of them? Try to delete manuals and labels.";

        foreach (string termToFind in Links.Keys)
        {
            Regex _regex = new Regex(@"\b" + termToFind + @"s?\b(?![^<>]*</)", RegexOptions.IgnoreCase);
            text = _regex.Replace(text, @"<a href=""" + Links[termToFind] + @".html"">$&</a>");
        }
        Console.WriteLine(text);
    }
}
使用系统;
使用System.Text.RegularExpressions;
使用System.Collections.Specialized;
公开课考试
{
公共静态void Main()
{
OrderedDictionary链接=新OrderedDictionary();
Links.Add(“了解有关添加手册和标签的更多信息”,“2”);
链接。添加(“删除手册和标签”,“3”);
链接。添加(“手册和标签”、“1”);
string text=“手册和标签有问题吗?了解有关添加手册和标签的详细信息。需要删除手册和标签吗?尝试删除手册和标签。”;
foreach(字符串项在Links.Keys中查找)
{

Regex\u Regex=new Regex(@“\b”+termToFind+@”s?\b(?![^]*您能否澄清“链接术语”的含义,并展示一个完整的示例,说明需要链接的
termToFind
文本所代表的内容?查看前后示例也会有所帮助。termToFind将是“了解更多关于手册和标签的信息”“手册和标签”,“删除手册和标签”。需要链接的文本插入可能是“手册和标签有问题?了解有关添加手册和标签的更多信息。需要删除手册和标签吗?尝试删除手册和标签。"理想的结果是:
与你的?有问题。需要摆脱它们吗?尝试。
啊哈!我真的很喜欢这样。唯一的问题是,从你的示例中,周围的文本将是相同的,无论匹配的术语是什么。如果我希望href第一个术语为1.html,第二个术语为2.html,等等uld我是否可以创建一个额外的捕获组,该组具有每个术语的目标HTML(与术语本身的顺序相同?)@TimWestover我正在研究这个问题!我更新了我的答案,以展示如何在
Regex.Replace
调用中使用字典和
MatchEvaluator
来查找适当的值。这太完美了。效果非常好。我对它进行了一些调整,以支持简单的复数形式(额外的s)。
var input = "Having trouble with your manuals and labels? Learn more about adding manuals and labels. Need to get rid of them? Try to delete manuals and labels.";
var terms = new[] 
{
    "Learn more about adding manuals and labels",
    "Delete Manuals and Labels",
    "manuals and labels"
};

var pattern = @"\b(" + String.Join("|", terms) + @")\b";
var replacement = @"<a href=""#"">$1</a>";
var result = Regex.Replace(input, pattern, replacement, RegexOptions.IgnoreCase);
Console.WriteLine(result);
var terms = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
    { "Learn more about adding manuals and labels", "2.html" },
    { "Delete Manuals and Labels", "3.html" },
    { "manuals and labels", "1.html" }
};

var pattern = @"\b(?:" + String.Join("|", terms.Select(t => t.Key)) + @")\b";
var result = Regex.Replace(input, pattern,
    m => String.Format(@"<a href=""{0}"">{1}</a>", terms[m.Value], m.Value),
    RegexOptions.IgnoreCase);

Console.WriteLine(result);
using System;
using System.Text.RegularExpressions;
using System.Collections.Specialized;

public class Test
{
    public static void Main()
    {
        OrderedDictionary Links = new OrderedDictionary();
        Links.Add("Learn more about adding manuals and labels", "2");
        Links.Add("Delete Manuals and Labels", "3");
        Links.Add("manuals and labels", "1");

        string text = "Having trouble with your manuals and labels? Learn more about adding manuals and labels. Need to get rid of them? Try to delete manuals and labels.";

        foreach (string termToFind in Links.Keys)
        {
            Regex _regex = new Regex(@"\b" + termToFind + @"s?\b(?![^<>]*</)", RegexOptions.IgnoreCase);
            text = _regex.Replace(text, @"<a href=""" + Links[termToFind] + @".html"">$&</a>");
        }
        Console.WriteLine(text);
    }
}