Регулярное выражение заменяет слово ссылкой

Я хочу написать регулярное выражение, которое заменит слово Париж ссылкой, потому что только слово не является частью ссылки.

Пример:

    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>.

Если вы хотите отблагодарить людей, которые вам помогают, войдите в систему, проголосуйте за полезные ответы и примите тот, который решил вашу проблему (если таковой есть).

Tomalak 09.11.2008 20:32
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
8 551
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Регулярное выражение:

!(<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 Leffler 09.11.2008 19:59

@Jonathan: в PHP вы можете использовать любой разделитель, если он одинаков в начале и в конце. Полезно, чтобы избежать экранирования содержимого ... @okoman: Я думаю, вы не должны избегать двойных кавычек в строке одинарных кавычек. И, возможно, вы можете улучшить RE с помощью незрелого совпадения.

PhiLho 09.11.2008 20:02

@Jonathan: Я думаю, что если бы я использовал нежадное сопоставление, было бы непонятно, что a-Element должен быть закрыт. (Поскольку открывающие теги должны встречаться так же часто, как и закрывающие.) Я использовал вычислитель регулярных выражений (regexp-evaluator.de). Он сгенерировал строку в кавычках, так что это не моя вина ;-) Изменяя это ...

okoman 09.11.2008 20:09

@okoman: я пробую твое регулярное выражение, но оно не совпадает с Парижем в «около Парижа»

AnhTu 09.11.2008 21:39

@AnhTu: Это так. Причина, по которой это не работает для вас, вероятно, заключается в том, что вы не используете неуклюжее регулярное выражение. "U" в конце регулярного выражения указывает на это. Я не знаю, на каком языке вы пытаетесь это сделать, но убедитесь, что вы используете неаккуратное регулярное выражение.

okoman 10.11.2008 01:07

Традиционный ответ на такой вопрос: используйте настоящий HTML-парсер. Потому что RE не очень хорошо работают в контексте. И HTML сложен, тег 'a' может иметь атрибуты или нет, в любом порядке, может иметь HTML в ссылке или нет и т. д.

Это сложно сделать за один шаг. Написание единственного регулярного выражения, которое делает это, практически невозможно.

Попробуйте двухэтапный подход.

  1. Разместите ссылку вокруг каждого «Парижа», независимо от того, есть ли еще одна ссылка.
  2. Найдите все неправильно вложенные ссылки (<a href = "..."><a href = "...">Paris</a></a>) и удалите внутреннюю ссылку.

Регулярное выражение для первого шага очень просто:

\bParis\b

Регулярное выражение для шага два немного сложнее:

(<a[^>]+>.*?(?!:</a>))<a[^>]+>(Paris)</a>

Используйте его для всей строки и замените его содержимым групп совпадений 1 и 2, эффективно удалив лишнюю внутреннюю ссылку.

Объяснение регулярного выражения # 2 простыми словами:

  • Найдите каждую ссылку (<a[^>]+>), за которой можно указать все, что не сопровождается закрывающей ссылкой (.*?(?!:</a>)). Сохраните его в группе матчей 1.
  • Теперь ищем следующую ссылку (<a[^>]+>). Убедитесь, что он есть, но не сохраняйте его.
  • Теперь поищите слово Париж. Сохраните его в группе матчей 2.
  • Ищите закрывающую ссылку (</a>). Убедитесь, что он есть, но не сохраняйте его.
  • Замените все содержимым групп 1 и 2, тем самым потеряв все, что вы не сохранили.

Подход предполагает следующие побочные условия:

  • Ваш входной HTML не сильно поврежден.
  • Ваш вариант регулярного выражения поддерживает нежадные квантификаторы (. *?) И отрицательные утверждения упреждающего просмотра нулевой ширины ((?!:...)).
  • Вы заключаете слово «Париж» только в ссылку на шаге 1, без дополнительных символов. Каждый «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: Никому не говори. ;)

Tomalak 24.07.2011 04:29

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

cdiggins 22.02.2011 00:27
  $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;
  }

Другие вопросы по теме