3

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

7 に答える 7

6

これを 1 ステップで行うのは困難です。それを行う単一の正規表現を書くことは事実上不可能です。

2 段階のアプローチを試してください。

  1. すでに別のリンクが存在するかどうかに関係なく、そこにあるすべての「パリ」にリンクを張ってください。
  2. 間違ってネストされたリンク ( ) をすべて見つけて<a href="..."><a href="...">Paris</a></a>、内側のリンクを削除します。

ステップ 1 の正規表現は非常に単純です。

\bParis\b

ステップ 2 の正規表現は、もう少し複雑です。

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

文字列全体でそれを使用し、一致グループ 1 と 2 のコンテンツに置き換えて、余分な内部リンクを効果的に削除します。

わかりやすい言葉での正規表現#2の説明:

  • すべてのリンク ( <a[^>]+>) を検索します。オプションで、それ自体ではないすべてのリンクの後に、終了リンク ( .*?(?!:</a>)) が続きます。一致グループ 1 に保存します。
  • 次のリンク ( ) を探します<a[^>]+>。そこにあることを確認しますが、保存しないでください。
  • 次に、パリという単語を探します。マッチ グループ 2 に保存します。
  • 閉じるリンク ( ) を探し</a>ます。そこにあることを確認しますが、保存しないでください。
  • すべてをグループ 1 と 2 の内容に置き換えると、保存しなかったものはすべて失われます。

このアプローチは、次の副条件を想定しています。

  • 入力 HTML はひどく壊れていません。
  • あなたの正規表現フレーバーは、貪欲でない量指定子 (.*?) とゼロ幅の負の先読みアサーション ( (?!:...)) をサポートしています。
  • 手順 1 のリンクでのみ "Paris" という単語をラップし、追加の文字はラップしません。すべての " Paris" が " <a href"...">Paris</a>" になるか、ステップ 2 が失敗します (2 番目の正規表現を変更するまで)。
  • ところで:正規表現#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>

于 2008-11-09T16:54:21.783 に答える
4

次の正規表現を検索できます。

(<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>";
    }
}
于 2008-11-11T09:07:51.567 に答える
3

このような質問に対する伝統的な答えは、実際の HTML パーサーを使用することです。REはコンテキストでの操作があまり得意ではないためです。HTML は複雑で、「a」タグは属性を持つかどうか、任意の順序で、リンクに HTML を持つかどうかなどを指定できます。

于 2008-11-09T16:32:10.733 に答える
0

この場合、正規表現の使用に限定されていない場合、XSLTは、XMLを「理解する」ため、この置換を定義できる言語に適しています。

2つのテンプレートを定義します。1つのテンプレートがリンクを検索し、本文に「パリ」が含まれていないリンクを削除します。別のテンプレートが他のすべてを検索し、それを単語に分割してタグを追加します。

于 2008-11-09T23:06:23.450 に答える
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;
  }
于 2010-08-12T12:55:43.907 に答える
0

正規表現:

!(<a.*</a>.*)*Paris!isU

置換:

$1<a href="Paris">Paris</a>

$1 は最初のサブパターンを参照します (少なくとも PHP では)。使用する言語によって、多少異なる場合があります。

これにより、「Paris」のすべての出現箇所が置換内のリンクに置き換えられます。「Paris」の前にすべての開始 a-Tags が閉じられたかどうかを確認するだけです。

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); 
?>

添加:

これは最善の解決策ではありません。この正規表現が機能しない状況の 1 つは、a-Element 内にない img-Tag がある場合です。その画像の title-Attribute を「Paris」に設定すると、この「Paris」も置き換えられます。そして、それはあなたが望むものではありません。それにもかかわらず、単純な正規表現で問題を完全に解決する方法はありません。

于 2008-11-09T16:29:21.567 に答える
-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;

もちろん、「バトン ルージュ」は次の 2 つのリンクになります。

<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モジュールがどこかになく、ハッシュをロードするだけでよい場合は驚くでしょう。

于 2008-11-10T01:01:26.993 に答える