我想写一个正则表达式,用链接代替单词Paris,因为只有单词没有准备好作为链接的一部分。
示例:
i'm living <a href="Paris" atl="Paris link">in Paris</a>, near Paris <a href="gare">Gare du Nord</a>, i love Paris.
会变成
i'm living.........near <a href="">Paris</a>..........i love <a href="">Paris</a>.
答案 0 :(得分:6)
这很难一步到位。编写单个正则表达式实际上是不可能的。
尝试两步法。
<a href="..."><a href="...">Paris</a></a>
),并删除内部链接。第一步的正则表达式很简单:
\bParis\b
第二步的正则表达式稍微复杂一些:
(<a[^>]+>.*?(?!:</a>))<a[^>]+>(Paris)</a>
在整个字符串中使用该字符串并将其替换为匹配组1和2的内容,从而有效地删除多余的内部链接。
用简单的词语解释正则表达式#2:
<a[^>]+>
),可选地后跟任何本身不是后跟关闭链接(.*?(?!:</a>)
)的链接。将其保存到匹配组1中。<a[^>]+>
)。确保它在那里,但不要保存它。</a>
)。确保它在那里,但不要保存它。该方法假设了这些方面的条件:
(?!:...)
)。Paris
”变为“<a href"...">Paris</a>
”,否则第二步将失败(直到您更改第二个正则表达式)。BTW:正则表达式#2明确允许这样的结构:
<a href="">in the <b>capital of France</b>, <a href="">Paris</a></a>
剩余链接来自第一步,第二步的替换结果将是:
<a href="">in the <b>capital of France</b>, Paris</a>
答案 1 :(得分:4)
您可以搜索此正则表达式:
(<a[^>]*>.*?</a>)|Paris
这个正则表达式匹配一个链接,它捕获到第一个(也是唯一的)捕获组,或者单词Paris。
仅当捕获组与任何内容不匹配时,才将匹配替换为您的链接。
E.g。在C#中:
resultString =
Regex.Replace(
subjectString,
"(<a[^>]*>.*?</a>)|Paris",
new MatchEvaluator(ComputeReplacement));
public String ComputeReplacement(Match m) {
if (m.groups(1).Success) {
return m.groups(1).Value;
} else {
return "<a href=\"link to paris\">Paris</a>";
}
}
答案 2 :(得分:3)
这个问题的传统答案:使用真正的HTML解析器。因为RE并不擅长在上下文中运行。 HTML很复杂,'a'标签可以有或没有属性,无论如何,链接中都可以包含HTML等等。
答案 3 :(得分:0)
正则表达式:
!(<a.*</a>.*)*Paris!isU
<强>替换强>
$1<a href="Paris">Paris</a>
$ 1引用第一个子模式(至少在PHP中)。根据您使用的语言,它可能会略有不同。
这应该用替换中的链接替换“Paris”的所有出现。它只是检查在“巴黎”之前是否所有打开的标签都已关闭。
PHP示例:
<?php
$s = 'i\'m living <a href="Paris" atl="Paris link">in Paris</a>, near Paris <a href="gare">Gare du Nord</a>, i love Paris.';
$regex = '!(<a.*</a>.*)*Paris!isU';
$replace = '$1<a href="Paris">Paris</a>';
$result = preg_replace( $regex, $replace, $s);
?>
增加:
这不是最好的解决方案。这种正则表达式不起作用的一种情况是你有一个img-Tag,它不在a-Element中。当您将该图像的title-Attribute设置为“Paris”时,此“Paris”也将被替换。这不是你想要的。 然而,我认为没有办法用一个简单的正则表达式完全解决你的问题。
答案 4 :(得分:0)
如果您在这种情况下不限于使用正则表达式,那么XSLT是您可以定义此替换的语言的不错选择,因为它“理解”XML。
您定义了两个模板: 一个模板查找链接并删除那些没有“Paris”作为正文文本的链接。另一个模板找到其他所有内容,将其拆分为单词并添加标签。
答案 5 :(得分:0)
$pattern = 'Paris';
$text = 'i\'m living <a href="Paris" atl="Paris link">in Paris</a>, near Paris <a href="gare">Gare du Nord</a>, i love Paris.';
// 1. Define 2 arrays:
// $matches[1] - array of links with our keyword
// $matches[2] - array of keyword
preg_match_all('@(<a[^>]*?>[^<]*?'.$pattern.'[^<]*?</a>)|(?<!\pL)('.$pattern.')(?!\pL)@', $text, $matches);
// Exists keywords for replace? Define first keyword without tag <a>
$number = array_search($pattern, $matches[2]);
// Keyword exists, let's go rock
if ($number !== FALSE) {
// Replace all link with temporary value
foreach ($matches[1] as $k => $tag) {
$text = preg_replace('@(<a[^>]*?>[^<]*?'.$pattern.'[^<]*?</a>)@', 'KEYWORD_IS_ALREADY_LINK_'.$k, $text, 1);
}
// Replace our keywords with link
$text = preg_replace('/(?<!\pL)('.$pattern.')(?!\pL)/', '<a href="">'.$pattern.'</a>', $text);
// Return link
foreach ($matches[1] as $k => $tag) {
$text = str_replace('KEYWORD_IS_ALREADY_LINK_'.$k, $tag, $text);
}
// It's work!
echo $text;
}
答案 6 :(得分:-2)
正则表达不替换。语言有。
语言和库也会从包含您关注的单词列表的数据库或文件中读取,并将URL与其名称相关联。这是我能想象的最简单的替换,我的单个正则表达式(perl用于替换语法。)
s/([a-z-']+)/<a href="http:\/\/en.wikipedia.org\/wiki\/$1">$1<\/a>/i
正确的名称可能会更好:
s/([A-Z][a-z-']+)/<a href="http:\/\/en.wikipedia.org\/wiki\/$1">$1<\/a>/gi;
当然“Baton Rouge”将成为两个链接:
<a href="http://en.wikipedia.org/wiki/Baton">Baton</a>
<a href="http://en.wikipedia.org/wiki/Rouge">Rouge</a>
在 Perl 中,您可以这样做:
my $barred_list_of_cities
= join( '|'
, sort { ( length $a <=> $b ) || ( $a cmp $b ) } keys %url_for_city_of
);
s/($barred_list_of_cities)/<a href="$url_for_city_of{$1}">$1<\/a>/g;
但同样,它是一个语言,它为正则表达式实现了一组操作,正则表达式不做任何事情。 (实际上,它是一个如此常见的应用程序,如果某个地方没有CPAN模块,我会感到惊讶,你只需要加载哈希值。