Я хочу написать регулярное выражение, которое заменит слово Париж ссылкой, потому что только слово не является частью ссылки.
Пример:
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>.





Регулярное выражение:
!(<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 этого изображения на «Париж», этот «Париж» также будет заменен. И это не то, что вам нужно. Тем не менее, я не вижу возможности полностью решить вашу проблему с помощью простого регулярного выражения.
Вы уверены в своем "!" обозначения? Какой диалект регулярного выражения вы используете?
@Jonathan: в PHP вы можете использовать любой разделитель, если он одинаков в начале и в конце. Полезно, чтобы избежать экранирования содержимого ... @okoman: Я думаю, вы не должны избегать двойных кавычек в строке одинарных кавычек. И, возможно, вы можете улучшить RE с помощью незрелого совпадения.
@Jonathan: Я думаю, что если бы я использовал нежадное сопоставление, было бы непонятно, что a-Element должен быть закрыт. (Поскольку открывающие теги должны встречаться так же часто, как и закрывающие.) Я использовал вычислитель регулярных выражений (regexp-evaluator.de). Он сгенерировал строку в кавычках, так что это не моя вина ;-) Изменяя это ...
@okoman: я пробую твое регулярное выражение, но оно не совпадает с Парижем в «около Парижа»
@AnhTu: Это так. Причина, по которой это не работает для вас, вероятно, заключается в том, что вы не используете неуклюжее регулярное выражение. "U" в конце регулярного выражения указывает на это. Я не знаю, на каком языке вы пытаетесь это сделать, но убедитесь, что вы используете неаккуратное регулярное выражение.
Традиционный ответ на такой вопрос: используйте настоящий HTML-парсер. Потому что RE не очень хорошо работают в контексте. И HTML сложен, тег 'a' может иметь атрибуты или нет, в любом порядке, может иметь HTML в ссылке или нет и т. д.
Это сложно сделать за один шаг. Написание единственного регулярного выражения, которое делает это, практически невозможно.
Попробуйте двухэтапный подход.
<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>», или второй шаг завершится ошибкой (пока вы не измените второе регулярное выражение).Кстати: регулярное выражение # 2 явно допускает такие конструкции:
<a href = "">in the <b>capital of France</b>, <a href = "">Paris</a></a>
Избыточная ссылка поступает из шага 1, результат замены шага 2 будет:
<a href = "">in the <b>capital of France</b>, Paris</a>
@systempuntoout: Никому не говори. ;)
Если вы не ограничивались использованием регулярных выражений в этом случае, XSLT - хороший выбор для языка, на котором вы можете определить эту замену, потому что он «понимает» XML.
Вы определяете два шаблона: Один шаблон находит ссылки и удаляет те ссылки, которые не содержат «Париж» в качестве основного текста. Другой шаблон находит все остальное, разбивает на слова и добавляет теги.
Регулярные выражения не заменяют. Языки делают.
Языки и библиотеки также будут читать из базы данных или файла, содержащего список слов, которые вам интересны, и связывать 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;
Конечно, «Батон-Руж» станет двумя связями для:
<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, который бы это делал, и вам просто нужно загрузить хеш.
Вы можете искать это регулярное выражение:
(<a[^>]*>.*?</a>)|Paris
Это регулярное выражение соответствует ссылке, которую оно захватывает в первую (и единственную) группу захвата, или слову Paris.
Замените совпадение своей ссылкой только в том случае, если группа захвата ничего не соответствует.
Например. в 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>";
}
}
s / new MatchEvaluator (ComputeReplacement) / ComputeReplacement / ... нет необходимости явно создавать MatchEvaluator.
$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;
}
Если вы хотите отблагодарить людей, которые вам помогают, войдите в систему, проголосуйте за полезные ответы и примите тот, который решил вашу проблему (если таковой есть).