4

URLオーソリティ(プロトコルとwww.が存在する場合はなし)とそれ以降のすべて(存在する場合)を抽出しようとしています。これまでの私の正規表現:

/^(?:http|https)?(?::\/\/)?(?:www\.)?(.*?)(\/.*)/;

これは、次のようなすべてを含む URL で機能します。

http://www.site.com/part1/part2?key=value#blub

しかし、パス キャプチャ グループをオプションとしてマークすると、次のようになります。

/^(?:http|https)?(?::\/\/)?(?:www\.)?(.*?)(\/.*)?/

もう似合わない。なんで?

ここで、最初のバリアントと一致させた場合:

http://site.com

:最初の値 (権限) と//site.com2 番目の値 (パス) として抽出します。

パスがなく、パスがオプションとしてマークされていないため、これが機能するとは思っていませんでした。しかし、私はこれらの2つのキャッチグループしか持っていないので、この結果についてはまだ疑問に思っています -(.*?)(\/.*)

http://jsfiddle.net/U2tKT/1/

誰かが私に何が悪いのか説明できますか。完全な URL 解析ソリューションへのリンクはありません。それらがたくさんあることは知っていますが、正規表現の何が問題なのか (およびそれをどのように解決するのか) を理解したいと考えています。

ありがとう。

4

3 に答える 3

2

regex の最後で/^(?:http|https)?(?::\/\/)?(?:www\.)?(.*?)(\/.*)?/(.*?)(?修飾子があるため) は、正規表現を満たすために、できるだけ一致させようとします。正規表現の最後の部分をoptionalにした(.*?)ため、 は何にも一致しないため、残りの正規表現を満たすために は何にも一致する必要はありませ(\/.*)?ん。一方、正規表現の最後の部分を必須にすると(\/.*)(.*?)が一致するために十分な一致が強制されました(\/.*)

于 2013-08-30T13:21:01.677 に答える
1

RFC3986

Internet Engineering Task Force ( IETF ) の Request for Comments (RFC) 文書番号 3986 というタイトルの「Uniform Resource Identifier (URI): Generic Syntax」 ( RFC3986 ) は、信頼できる標準であり、アプリケーションを構成するすべてのコンポーネントの正確な構文を記述しています。有効なジェネリック URI (Uniform Resource Identifier)。付録 Bは、必要な正規表現を示しています。

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?

この正規表現では、URI 部分は次のように格納されます。

scheme = $2
authority = $4
path = $5
query = $7
fragment = $9

上記の正規表現を文書化する目的で、コメントとインデントを使用して自由にスペースを空けるモードで書き直し、指定されたすべての主要部分を解析するテスト済みの PHP スクリプトの形式でここに示します。 URI 文字列:

PHP ソリューション:

<?php // test.php Rev:20130830_0800

$re_rfc3986_parse_generic_uri = '%
    # Parse generic URI according to RFC3986 Appendix B.
    ^             # Anchor to start of string.
    (?:           # Group for optional scheme.
      ([^:/?#]+)  # $1: Uri SCHEME.
      :           # Scheme ends with ":".
    )?            # Scheme is optional.
    (?:           # Group for optional authority.
      //          # Authority starts with "//"
      ([^/?#]*)   # $2: Uri AUTHORITY.
    )?            # Authority is optional.
    ([^?#]*)      # $3: Uri PATH (required).
    (?:           # Group for optional query.
      \?          # Query starts with "?".
      ([^#]*)     # $4: Uri QUERY.
    )?            # Query is optional.
    (?:           # Group for optional fragment.
      \#          # Fragment starts with "#".
      (.*)        # $5: Uri FRAGMENT.
    )?            # Fragment is optional.
    $             # Anchor to end of string.
    %x';

$text = "http://www.site.com/part1/part2?key=value#blub";

if (preg_match($re_rfc3986_parse_generic_uri, $text, $matches)) {
    print_r($matches);
} else {
    echo("String is not a valid URI");
}
?>

元の正規表現に対して 2 つの機能上の変更が行われました。1.) 不要なキャプチャ グループが非キャプチャに変換され、2.)$文字列アンカーの終わりが式の最後に追加されました。番号付きのキャプチャ グループを使用するのではなく、名前付きのキャプチャ グループを使用することで、さらに読みやすいバージョンを作成できますが、JavaScript 構文に直接移行することはできないことに注意してください。

PHP スクリプト出力:

Array
(
[0] => http://www.site.com/part1/part2?key=value#blub
[1] => http
[2] => www.site.com
[3] => /part1/part2
[4] => key=value
[5] => blub
)

JavaScript ソリューション:

以下は、有効な URI をさまざまなコンポーネントに分解する、テスト済みの JavaScript 関数です。

// Parse a valid URI into its various parts per RFC3986.
function parseValidURI(text) {
    var uri_parts;
    var re_rfc3986_parse_generic_uri =
    /^(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/;
    // Use String.replace() with callback function to parse the URI.
    text.replace(re_rfc3986_parse_generic_uri,
        function(m0,m1,m2,m3,m4,m5) {
            uri_parts = {
                scheme      : m1,
                authority   : m2,
                path        : m3,
                query       : m4,
                fragment    : m5
            };
            return; // return value is not used.
        });
    return uri_parts;
}

返されたオブジェクトの非パス プロパティはundefined、URI 文字列に存在しない場合があることに注意してください。また、URI 文字列がこの正規表現と一致しない場合 (つまり、明らかに無効である場合)、返される値はundefinedです。

ノート:

  • 必要なジェネリック URI の唯一のコンポーネントはパスです(パス自体は空である場合があります)。
  • 空の文字列は有効な URI です。
  • 上記の正規表現は URI を検証しませんが、指定された有効な URI を解析します。
  • 上記の正規表現が URI 文字列と一致しない場合、その文字列は有効な URI ではありません。ただし、その逆は当てはまりません。文字列が上記の正規表現に一致する場合、URI が有効であることを意味するのではなく、URI として解析可能であることを意味するだけです。

URI を検証し、さらに分解することに興味がある人のために、RFC3986 の付録 A で定義されているすべての部分を取り上げ、それらを正規表現構文に変換する記事を書きました。見る:

正規表現 URI 検証

ハッピー正規表現!

于 2013-08-30T17:06:54.657 に答える