首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >词汇表函数的RegEx

问词汇表函数的RegEx
EN

Stack Overflow用户
提问于 2013-10-11 15:07:25
回答 3查看 134关注 0票数 3

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

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

我有一个RegEx来查找/替换整个单词(good ol‘\b),这非常有用,除了在其他链接术语中找到的链接术语之外。而不是:

代码语言:javascript
复制
<a href="#">Learn more about manuals and labels</a>

我最后

代码语言:javascript
复制
<a href="#">Learn more about <a href="#">manuals and labels</a></a>

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

代码语言:javascript
复制
Learn more about <a href="#">manuals and labels</a>

没有外部链接我真的需要。

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

代码语言:javascript
复制
Regex _regex = new Regex("\\b" + termToFind + "(|s)" + "\\b", RegexOptions.IgnoreCase);

string resultingText = _regex.Replace(textThatNeedsLinksInserted, "<a>" + "$&".Replace(" ", "_") + "</a>));

然后,在所有的条件完成后,删除"_",这将是完美的。"Learn_more_about_manuals_and_labels“不符合”手册和标签“,一切都很好。

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

是否有一个允许我在原始匹配中用"_“替换空白的RegEx?还是有不同的解决方案在逃避我?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-11 16:45:53

从使用嵌套链接的示例中可以看出,您正在对这些术语进行单独传递,并执行多个Regex.Replace调用。因为您使用的是正则表达式,所以您应该让它完成繁重的任务,并将一个很好的模式组合在一起,从而利用交互。

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

代码语言:javascript
复制
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);

现在,为了解决每个术语对应的href值的问题,您可以使用字典并将regex更改为使用MatchEvaluator,它将返回自定义格式并从字典中查找值。字典还通过传入StringComparer.OrdinalIgnoreCase来忽略大小写。我稍微调整了模式,在组的开头添加了?:,使其成为一个非捕获组,因为我不再像在第一个示例中那样引用捕获的项。

代码语言:javascript
复制
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);
票数 1
EN

Stack Overflow用户

发布于 2013-10-11 16:54:01

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

代码语言:javascript
复制
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);
    }
}

ideone演示

我添加的负展望((?![^<>]*</))阻止了替换之前已经替换过的部分,该部分位于锚标记之间。

票数 1
EN

Stack Overflow用户

发布于 2013-10-11 15:36:17

首先,可以通过使用manuals and labels防止Regex查找Learn more about manuals and labels。修改您的正则表达式如下所示:

代码语言:javascript
复制
(?<!Learn more about )(manuals and labels)

如果不是你的具体要求,我会提出一个不同的解决方案。您应该为正则表达式定义规则或优先级列表,或者两者都定义。一个可能的规则可以是“始终先搜索匹配最多字符的正则表达式”。然而,这需要您的regexs始终是固定长度。而且,它也不能阻止一个正则表达式使用和替换其他正则表达式(甚至可能是相同大小的)所匹配的字符。

当然,您需要为每个regexs添加一个额外的回顾和展望,以避免替换替换元素中的字符串。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19321459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档