2

文字列内のプレーンテキストのURL(文字列には複数のURLを含めることができます)を置き換える正規表現を次のように検索しています。

 <a href="url">url</a>

そして私はこれを見つけました:http: //mathiasbynens.be/demo/url-regex

私はdiegoperiniの正規表現を使用したいと思います(テストによるとこれが最高です):

_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS

しかし、文字列内のすべてのURLをグローバルに置き換えたいと思います。私がこれを使うとき:

/_(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?_iuS/g

それは機能しません。この正規表現をグローバルにするにはどうすればよいですか。最初のアンダースコアと最後の「_iuS」はどういう意味ですか?

phpで使用したいので、以下を使用しています。

preg_replace($regex, '<a href="$0">$0</a>', $examplestring);
4

2 に答える 2

0

アンダースコアは正規表現の区切り文字であり、i、u、およびSはパターン修飾子です。

i(PCRE_CASELESS)

If this modifier is set, letters in the pattern match both upper and lower 
case letters.

U(PCRE_UNGREEDY)

This modifier inverts the "greediness" of the quantifiers so that they are 
not greedy by default, but become greedy if followed by ?. It is not compatible
with Perl. It can also be set by a (?U) modifier setting within the pattern 
or by a question mark behind a quantifier (e.g. .*?).

S

When a pattern is going to be used several times, it is worth spending more 
time analyzing it in order to speed up the time taken for matching. If this 
modifier is set, then this extra analysis is performed. At present, studying 
a pattern is useful only for non-anchored patterns that do not have a single 
fixed starting character.

詳細については、http://www.php.net/manual/en/reference.pcre.pattern.modifiers.phpを参照してください。

/ ... / gを追加したときに、別の正規表現区切り文字に加えて、PCREに存在しない修飾子gを追加したため、機能しませんでした。

于 2012-09-10T13:43:17.120 に答える
0

@verdesmaraldに同意し、次の関数でこのパターンを使用しました。

$string = preg_replace_callback(
        "_(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?_iuS",
        create_function('$match','
            $m = trim(strtolower($match[0]));
            $m = str_replace("http://", "", $m);
            $m = str_replace("https://", "", $m);
            $m = str_replace("ftp://", "", $m);
            $m = str_replace("www.", "", $m);

            if (strlen($m) > 25)
            {
                $m = substr($m, 0, 25) . "...";
            }

            return "<a href=\"$match[0]\">$m</a>";
                '), $string);

    return $string;

それはトリックを行い、私が抱えていた問題を解決するようです。@verdesmaraldが言ったように、^文字と$文字を削除すると、pre_replace_callback()でもパターンが機能するようになりました。

私が気になるのは、パターンがどれだけ効率的かということだけです。ビジー/トラフィックの多いWebアプリで使用すると、ボトルネックが発生する可能性がありますか?

アップデート

上記の正規表現パターンは、URLのパスセクションの最後にトレイルドットがある場合に壊れhttp://www.mydomain.com/page.ます。これを解決するために、正規表現パターン^.の最後の部分を次のように追加して変更しました[^\s^.]。私が読んでいるように、末尾のスペースやドットと一致しないでください。

これまでの私のテストでは、正常に機能しているようです。

于 2013-01-19T01:33:38.287 に答える