2

はぁ、また正規表現トラブル。

私は以下を持っています$text

[img]http://www.site.com/logo.jpg[/img]

and 

[url]http://www.site.com[/url]

私は正規表現を持っています:

$text = preg_replace("/(?<!(\[img\]|\[url\]))([http|ftp]+:\/\/)?\S+[^\s.,>)\];'\"!?]\.+[com|ru|net|ua|biz|org]+\/?[^<>\n\r ]+[A-Za-z0-9](?!(\[\/img\]|\[\/url\]))/","there was link",$text);

[img]ポイントは、前にor[url]がなく、後に[/img]orがない場合にのみ url を置き換えること[/url]です。前の例の出力では、次のようになります。

there was link

and

there was link

URL と後読みおよび先読み正規表現の両方が別々に正常に動作しています。

$text = "[img]bash.org/logo.jpg[/img]";

$text = preg_replace("/(?<!(\[img\]|\[url\]))bash.org(?!(\[\/img\]|\[\/url\]))/","there was link",$text);

echo $text leaves everything as is and gives me [img]bash.org/logo.jpg[/img] 

問題は、ルックアラウンドと URL 正規表現の組み合わせにあると思います。私の間違いはどこですか?

したい

http://www.google.comを「there was link」に置き換えますが、「[url] http://www.google.com[/url]」のままにします。

私は得ています

http://www.google.comは「リンクがありました」に置き換えられ、[url] http://www.google.com[/url]は「リンクがありました」に置き換えられました

テストするPHPコードはこちら

<?php

$text = "[url]http://www.google.com[/url] <br><br> http://www.google.com"; 
         // should NOT be changed                  //should be changed    

$text = preg_replace("/(?<!\[url\])([http|ftp]+:\/\/)?\S+[^\s.,>)\];'\"!?]\.+[com|ru|net|ua|biz|org]+\/?[^<>\n\r ]+[A-Za-z0-9](?!\[\/url\])/","there was link",$text);

echo $text;

echo '<hr width="100%">';

$text = ":) :-) 0:) 0:-) :)) :-))";

$text = preg_replace("/(?<!0):-?\)(?!\))/","smiley",$text);

echo $text; // lookarounds work

echo '<hr width="100%">';

$text = "http://stackoverflow.com/questions/2482921/regexp-exclusion";

$text = preg_replace("/([http|ftp]+:\/\/)?\S+[^\s.,>)\];'\"!?]\.+[com|ru|net|ua|biz|org]+\/?[^<>\n\r ]+[A-Za-z0-9]/","it's a link to stackoverflow",$text);

echo $text; // URL pattern works fine

?>
4

4 に答える 4

2

私があなたを理解していると仮定すると、URL が url タグまたは img bbcode タグ内にない限り、$input 内のすべての URL を「link was here」という単語に置き換えたいと考えています。ルックアラウンド アサーションが機能しない理由は、これらの部分が実際に非常に貪欲な URL パターンと一致しているためです (これは、意図しない多くのことを実行していると確信しています)。他のテキスト内の任意の有効な URL (クエリ文字列を含む) に一致し、それに付けられたタグにも一致しないパターンを記述することは、必ずしも最も単純なことではありません。特に、現在のパターンには http:// または ftp:// がオプションとして含まれているためです。

成功する可能性が高い唯一の方法は、URL を構成する一連の厳密なルールを決定することです。

于 2010-08-14T14:01:31.527 に答える
0

あなたの質問を完全に理解するのは難しいですが、リバース BBcode を行っているようです。で、タグで囲まれていたら放っておいて? その場合、URL の正規表現は非常に複雑であることで知られているため、興味深い問題が発生することになると思います。

これを必要以上に複雑にしている可能性があると思います。代わりに、BBcode の間にあるものはすべて変更します。これが私が起こる必要があると思うことです:

  1. 文字列セグメント「[url]」を見つけます
  2. それを進めるものは何でも捕獲する
  3. 文字列セグメント「[/url]」が表示されたら、キャプチャを終了します

それは簡単な正規表現です:

$string = "[url]http://www.google.com[/url] <br><br> http://www.google.com"; 

$replace = "there was link";
$text = preg_replace_all($regex,$replace,$text);
echo $text;

これはまさにあなたが求めたものではないことはわかっています (実際には、おそらく正反対です) が、同じ結果が得られ、はるかに簡単になります。

おそらく、この正規表現で否定先読みを使用してみることができますが、適切な結果が得られるかどうかはわかりません。

$regex = "#(?!\[url\])(.*)(?!\[/url\])#";

1 つの重要な注意: これはユーザー入力をサニタイズしません。必ずこれを行ってください。ただし、ロジックを分離して、何をどこで行っているかを簡単に確認できるようにします。ライブラリを使用してこれを行うこともできます。これは、より簡単でおそらく安全だからです。

于 2010-08-14T15:42:19.767 に答える
0

最終的な正規表現は次のようになります。

(?<!\[img\]|\[url\])((^|\s)([\w-]+://|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))(?!\[\/img\]|\[/url\])

例:

<?php

$text = "

[img]http://google.com/logo.jpg[/img]

[img]www.google.com/logo.jpg[/img]

[img]http://www.google.com/logo.jpg[/img]

[url]http://google.com/logo.jpg[/url]

[url]www.google.com/logo.jpg[/url]

[url]http://www.google.com/logo.jpg[/url]

www.google.com/logo.jpg

http://google.com/logo.jpg

http://www.google.com/logo.jpg

";

$text = nl2br($text);


$text = preg_replace("'(?<!\[img\]|\[url\])((^|\s)([\w-]+://|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))(?!\[\/img\]|\[/url\])'i","<font color=\"#ff0000\">link</font>",$text);

echo $text;

?>

出力:

[img]http://google.com/logo.jpg[/img]

[img]www.google.com/logo.jpg[/img]

[img]http://www.google.com/logo.jpg[/img]

[url]http://google.com/logo.jpg[/url]

[url]www.google.com/logo.jpg[/url]

[url]http://www.google.com/logo.jpg[/url]

link

link

link

トリックは、 ^ または \s で始まるリンクのみを置き換えることです。この問題を解決する他の方法は見つかりませんでした。

于 2010-08-14T17:54:14.823 に答える
0

私の間違いはどこですか?

まあ、最悪の間違いは後読みです。それは必要ではなく、必要以上に仕事を難しくしています。既存のタグが適切に形成されていると仮定すると、わざわざ開始タグを探す必要はありません。その存在は、終了タグの存在によって暗示されます。

編集: あなたの正規表現には、後読み以外にもいくつかの問題がありますが、それを試して修正する価値はないようです。代わりに、RegexBuddy の組み込みの便利な正規表現ライブラリから正規表現を取得し、それに先読みを追加しました。

この正規表現を試してください (またはideoneでの動作を確認してください):

'_\b(?>
     (?>www\.|ftp\.|(?:https?|ftp|file)://)  # scheme or subdomain
     [-+&@#/%=~|$?!:,.\w]*[+&@#/%=~|$\w]     # everything else
   )(?!\[/(?:img|url)\])
 _x'

問題が前方または後方、先行または後続などの観点から記述できるからといって、正規表現をそのように設計する必要があるという意味ではありません。特に後読みは、最初に使用するツールであって はなりません。

于 2010-08-16T04:55:35.807 に答える