我有一些关键字(单个单词或几个单词)列表,我想用一些URL替换它们。
像:
伦敦将被<a
href="http://www.mysite/london-events/london">London</a>
伦敦的足球赛事<a
href="http://www.mysite/footbal-events/london">
Football events in London</a>
伦敦足球赛事<a
href="http://www.mysite/footbal-events/london">
London football events</a>
伦敦足球赛事<a
href="http://www.mysite/footbal-events/london">
Football events London</a>
伦敦的派对网站<a
href="http://www.mysite/party-sites/london">
party sites in London</a>
伦敦派对网站<a
href="http://www.mysite/party-sites/london">
London party sites</a>
我将上面的键/值放在字典中,键中的关键字和值中的URL并替换为
内容如下:
伦敦是一个伟大的城市,并拥有 伦敦的足球赛事,但派对 伦敦的景点也不错。伦敦 足球赛事很棒 伦敦派对网站。享受伦敦!
替换键/值的代码:
private static string ParsedContents(some arguments list here...)
{
Dictionary<string, string> keyWords = GetKeywordsAndEntityWithURL(some arguments list here...);
StringBuilder parsedContents = new StringBuilder(contents);
foreach (var keyWord in keyWords)
{
string replacedString = Regex.Replace(parsedContents.ToString(), "\\b" + keyWord.Key + "\\b", keyWord.Value, RegexOptions.IgnoreCase);
parsedContents.Remove(0, parsedContents.Length);
parsedContents.Append(replacedString);
}
// retrun parsed contents as string.
return parsedContents.ToString();
}
当我运行我的代码时,只有'伦敦'替换为'<a href="http://www.mysite/london-events/london">London</a>'
而其他所有代码保持不变,但如果我从关键字中删除'伦敦'它就可以正常工作。
你可以帮我解决一下我如何匹配整个字符串。
要替换的内容和网址是假的:
由于
答案 0 :(得分:2)
因为您要链接的某些短语包含您想要链接的其他短语,并且链接本身也将包含这些短语,如果您想避免棘手的正则表达式,则必须分两个阶段进行:
阶段1:将每个短语替换为与其他任何内容都不匹配的短语的唯一ID:
IComparer<string>
按字母顺序按长度对字符串进行排序。请注意,相同长度的字符串仍然比较不同是很重要的,或者您不能将它们都存储在字典中。string.Replace
替换你需要的短语
对待只有不同的短语
案例作为不同的短语,即
“伦敦的派对网站”与众不同
来自“伦敦的派对网站”和每个
将需要一个单独的ID。阶段2:将所有占位符ID替换为生成的链接。
这是一个可以做到的课程:
class TextLinker : IComparer<string>
{
private SortedDictionary<string, string> phrasesToUrls;
public TextLinker()
{
// Pass self as IComparer to sort dictionary using Compare method.
phrasesToUrls = new SortedDictionary<string, string>(this);
}
public void AddLink(string phrase, string URL)
{
phrasesToUrls.Add(phrase, URL);
}
public string Link(string text)
{
// phase 1: replace phrases to be linked with unique placeholders
Dictionary<string, string> placeholdersToLinks =
new Dictionary<string, string>();
foreach (KeyValuePair<string, string> pair in phrasesToUrls)
{
// Replace phrases with placeholders.
string placeholder = Guid.NewGuid().ToString();
text = text.Replace(pair.Key, placeholder);
// Create dictionary of links by placeholder
string link = string.Format(
"<a href=\"{0}\">{1}</a>",
pair.Value,
pair.Key);
placeholdersToLinks.Add(placeholder, link);
}
// Phase 2: replace unique placeholders with links.
foreach (KeyValuePair<string, string> pair in placeholdersToLinks)
{
text = text.Replace(pair.Key, pair.Value);
}
return text;
}
public int Compare(string x, string y)
{
if (x.Length > y.Length) return -1;
if (x.Length < y.Length) return +1;
// Equal length strings still need to be differentiated, otherwise
// they will be treated as the same key by the dictionary.
return x.CompareTo(y);
}
}
这是一个使用它的例子:
string input = "London is a great city and have football events " +
"in London but party sites in London are also good. London " +
"football events are great along with London party sites. " +
"Enjoy London!";
TextLinker linker = new TextLinker();
linker.AddLink(
"Football events in London",
"http://www.mysite/footbal-events/london");
linker.AddLink(
"football events in London",
"http://www.mysite/footbal-events/london");
linker.AddLink(
"London football events",
"http://www.mysite/footbal-events/london");
linker.AddLink(
"London",
"http://www.mysite/london-events/london");
linker.AddLink(
"Party sites in London",
"http://www.mysite/party-sites/london");
linker.AddLink(
"party sites in London",
"http://www.mysite/party-sites/london");
linker.AddLink(
"London party sites",
"http://www.mysite/party-sites/london");
string output = linker.Link(input);
您还可以重载AddLink
方法,以自动生成具有替代大小写的短语。
答案 1 :(得分:1)
如果您首先用URL替换所有较长的字符串,而不是在URL中设置“London”,您可以设置另一个单词,例如“Lxondon”,该怎么办?将包含London的所有字符串替换为相应的URL后,您也可以用其URI替换London。最后,您将在所有文本中将“Lxondon”替换为“伦敦”。
这不是一个非常好的方法,但我认为它会起作用。
答案 2 :(得分:0)
答案 3 :(得分:0)
要详细说明其他答案,您必须先放置最长且更复杂的字符串替换。例如
伦敦的足球赛事
伦敦
如果你在你的例子中做伦敦,并用肯特替换它,任何“伦敦足球赛事”的实例将成为“肯特的足球赛事”,并且不会满足正则表达式。
PS:如果您经常使用它,可能需要考虑将其作为字符串的扩展方法。
答案 4 :(得分:0)
如果您以递归方式进行替换,该怎么办?即,每次找到匹配项时,您都将其替换为字典中的文本并重复该过程,但仅针对尚未匹配的文本部分。
答案 5 :(得分:0)
正如其他人所说:
foreach
,您无法保证获得所需的订单。故事的道德:我担心,发现和替换(即使使用正则表达式)也不会削减它。
可能有更聪明的方法可以做到这一点,但在我的脑海中,这里有一些需要研究的东西,进入伪代码:
while(!input.EOS)
for(longest to shortest key)
if(input.indexOf(key) = 0)
output += input.replace(key, url)
input = remained of input
matched = true
if !matched then move first word from input to output
你必须稍微调整它,特别是因为空白问题(你如何/在哪里匹配空格和非单词字符?)这是另一个让你入门的提示:^\s*(.+?)\s*\b
答案 6 :(得分:0)
您可以做的一件事是:
将键(从大到小)连接成一个正则表达式(假设此处dictionary
是IDictionary<string, string>
):
var pattern = string.Join(
"|",
dictionary.Keys.OrderByDescending(k => k.Length).Select(Regex.Escape).ToArray()
);
var regex = new Regex("(" + pattern + ")", RegexOptions.ExplicitCapture);
请注意在转换函数中使用Regex.Escape
:我们不希望密钥中的特殊正则表达式字符出现错误。
快速测试表明,.NET的正则表达式引擎将按照它们在模式中出现的顺序尝试匹配。这意味着,如果订购正确,将首先尝试更长的密钥,然后正则表达式将继续,寻找新的匹配。
然后,您可以循环遍历匹配并从旧版本中构建新字符串,而不是多次扫描输入字符串。这两种技术的结合将消除这两个问题:过早的和重复匹配。
string input = "..."; // This is your input string.
int last = 0;
var output = new StringBuilder(input.Length);
foreach (Match match in regex.Matches(input)) {
output.Append(input.Substring(last, match.Index - last); // Appends text between matches.
output.AppendFormat(
"<a href=\"{1}\">{0}</a>",
match.Value,
dictionary[match.Value]
);
last = match.Index + match.Length; // Moves the index to the end of this match.
}
不包括错误检查。此外,正则表达式本身可能会以\b
形式的\b(...)\b
锚点受益。这是未经测试的,我上床睡觉了。