2

HTTP Accept ヘッダーを解析して、そこからすべての詳細を抽出しようとしています。私は次の仮定をしています:

各エントリは、少なくとも で始まり、少なくとも を含む必要があります。type/subtypeオプションで、+basetype たとえばtext/htmlまたはapplication/xhtml+xml エントリはコンマで区切られます。最初の の後type/subtypeに、エントリには、セミコロンで区切られた可変数のパラメータkey=valueペアを含めることができます (セミコロン間では空白を使用できますが、ペア間=では空白を使用できませんkey=value)。たとえば、application/xhtml+xml; q=0.8; test=hello

このすべての情報を配列に取得したいと考えています。

私が現在持っているのはpreg_match_all('/([^,;\/=\s]+)\/([^,;\/=\s+]+)(\+([^,;\/=\s+]+))?(\s?;\s?([^,;=]+)=([^,;=]+))*/', $header, $result, PREG_SET_ORDER);、私の考えでは、タイプの最初のキャプチャグループ、次にサブタイプのキャプチャグループ、次にベースタイプのオプションのグループ、次に で区切られたオプションの繰り返しグループを提供するもので;、2つを含みますkey=value

ヘッダー文字列で使用すると、次のようになりapplication/xhtml+xml; q=0.9; level=3 , text/html,application/json;test=helloます。

Array
(
    [0] => Array
        (
            [0] => application/xhtml+xml; q=0.9; level=3 
            [1] => application
            [2] => xhtml
            [3] => +xml
            [4] => xml
            [5] => ; level=3 
            [6] => level
            [7] => 3 
        )

    [1] => Array
        (
            [0] => text/html
            [1] => text
            [2] => html
        )

    [2] => Array
        (
            [0] => application/json;test=hello 
            [1] => application
            [2] => json
            [3] => 
            [4] => 
            [5] => ;test=hello 
            [6] => test
            [7] => hello 
        )

)

key=valueこれは問題ありませんが、最初のエントリ ( application/xhtml+xml; q=0.9; level=3)に対して最後のみが指定され、q=0.9がありません。

正規表現を 1 つだけ使用しながら、各一致にすべての (可変数の) パラメータを含める方法はありますか、またはkey=valueペアに別の正規表現/関数を使用する必要がありますか?

編集:

私が望む配列結果の種類は次のとおりです(明らかに、各コンテンツタイプのアイテム0、3、5、8などは不要ですが、除外できるかどうかはわかりません):

Array
(
    [0] => Array
        (
            [0] => application/xhtml+xml; q=0.9; level=3 
            [1] => application
            [2] => xhtml
            [3] => +xml
            [4] => xml
            [5] => ; q=0.9 
            [6] => q
            [7] => 0.9 
            [8] => ; level=3 
            [9] => level
           [10] => 3 
        )

    [1] => Array
        (
            [0] => text/html
            [1] => text
            [2] => html
        )

    [2] => Array
        (
            [0] => application/json;test=hello 
            [1] => application
            [2] => json
            [3] => 
            [4] => 
            [5] => ;test=hello 
            [6] => test
            [7] => hello 
        )

)

これにより、さらに正規表現や文字列関数を実行しなくても、各パラメーターのキーと値を取得できます。

編集

Kaの回答を受け入れました。必要なものはすべて揃っているようです。彼のパターン(?:\G\s?,\s?|^)(\w+)\/(\w+)(?:\+(\w+))?|(?<!^)\G(?:\s?;\s?(\w+)=([\w\.]+))を同じ文字列で (設定された順序なしで) 使用すると、次の結果が得られます。

Array
(
    [0] => Array
        (
            [0] => application/xhtml+xml
            [1] => ; q=0.9
            [2] => ; level=3
            [3] =>  , text/html
            [4] => ,application/json
            [5] => ;test=hello
        )

    [1] => Array
        (
            [0] => application
            [1] => 
            [2] => 
            [3] => text
            [4] => application
            [5] => 
        )

    [2] => Array
        (
            [0] => xhtml
            [1] => 
            [2] => 
            [3] => html
            [4] => json
            [5] => 
        )

    [3] => Array
        (
            [0] => xml
            [1] => 
            [2] => 
            [3] => 
            [4] => 
            [5] => 
        )

    [4] => Array
        (
            [0] => 
            [1] => q
            [2] => level
            [3] => 
            [4] => 
            [5] => test
        )

    [5] => Array
        (
            [0] => 
            [1] => 0.9
            [2] => 3
            [3] => 
            [4] => 
            [5] => hello
        )

)

ここから、インデックス 1 の配列を使用して連想配列をコンパイルし、個々のコンテンツ タイプとそのパラメーターの境界を判断できます。

Ka の助けに感謝します。

編集:

式を再度変更しました。式は、text/*. したがって、式は次のようになります。

(?:\G\s?,\s?|^)(\w+|\*)\/(\w+|\*)(?:\+(\w+))?|(?<!^)\G(?:\s?;\s?(\w+)=([\w\.]+))
4

2 に答える 2

3

独自の関数を作成するのではなく、php の解析関数を使用することをお勧めします。

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

特にあなたの状況では:

http://php.net/manual/en/function.http-parse-headers.php

于 2013-03-18T09:20:10.817 に答える
1

目的の出力とは少し異なりますが、必要のない値を除いてすべての値を安全に取得できます。

RegEx: (\w+)\/(\w+)(?:\+(\w+))?|(?:\s?;\s?(\w+)=([\w\.]+)) (グローバル フラグgを使用)
説明されたデモ: http://regex101.com/r/fM1gJ2
編集: これは regexorで構成されているため、既に検証済みのヘッダーで使用することをお勧めします。この正規表現を使用\w+\/\w+(\+\w+)?(\s?;\s?\w+=[\w\.]+)*して検証できます。

また

線に沿った何か:

正規表現: デモが必要だと思う回数だけ(\w+)\/(\w+)(?:\+(\w+))?(?:\s?;\s?(\w+)=([\w\.]+))?
最後の部分を繰り返します: http://regex101.com/r/yI6uS1(?:\s?;\s?(\w+)=([\w\.]+))?

アップデート:

グローバル フラグを使用して同時に検証とキャプチャg
RegEx:デモの(\w+)\/(\w+)(?:\+(\w+))?|(?<!^)\G(?:\s?;\s?(\w+)=([\w\.]+))
説明: http://regex101.com/r/bR7kU2
更新 (コンテンツ タイプは常にコンマで区切る必要があります)
RegEx:(?:\G\s?,\s?|^)(\w+)\/(\w+)(?:\+(\w+))?|(?<!^)\G(?:\s?;\s?(\w+)=([\w\.]+)) デモ: http://regex101. com/r/nG4oV0

v2 の短い反復終了パターン:文字セット(?:\s?;\s?((?4))=((?5)))?を増やす場合に備えて、ここで説明します。または、この正規表現を使用して不要なデータを配列に保存できるようにすると、さらに短くなります。 key=value

(\w+)\/(\w+)(?:\+(\w+))?(\s?;\s?([\w-]+)=([\w!:\$\.-]+))?((?4))?

((?4))?必要に応じて繰り返します。こちらを参照してください

于 2013-03-18T13:59:57.193 に答える