我正在尝试解析HTTP Accept标头,以从中提取所有细节。
我做出以下假设:
每个条目必须以开头并至少包含
type/subtype
,可选带有
+basetype
例如
text/html
或
application/xhtml+xml
条目用逗号分隔。
在初始
类型/子类型
,该条目可能包含可变数量的参数
key=value
对,用分号分隔(分号之间允许空白,但分号之间不允许空白
=
属于
key=值
成对)
例如
application/xhtml+xml; q=0.8; test=hello
我想把所有这些信息都放到一个数组中。
我现在拥有的是
preg_match_all('/([^,;\/=\s]+)\/([^,;\/=\s+]+)(\+([^,;\/=\s+]+))?(\s?;\s?([^,;=]+)=([^,;=]+))*/', $header, $result, PREG_SET_ORDER);
在我看来,它给出了一个带有类型的初始捕获组,然后是一个带有子类型的捕获组,再是一个带基本类型的可选捕获组,最后是一个可选重复捕获组,由
;
,包含两个
key=值
.
与标题字符串一起使用时
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=值
为第一个条目提供(
application/xhtml+xml; q=0.9; level=3
)
q=0.9
缺少。
是否有任何方法可以在每次匹配中包含所有(可变数量)参数,同时仍然只使用一个正则表达式,或者是否必须为
key=值
对?
编辑:
我想要的数组结果是这样的(显然,每种内容类型的项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
)
)
这使我可以获取每个参数的键和值,而无需执行任何进一步的regexp或字符串函数。
编辑
我已经接受了
灵魂
的答案,这似乎给了我所需要的一切。
使用他的模式
(?:\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的数组编译关联数组,以确定具有其参数的各个内容类型之间的边界。
非常感谢卡的帮助。
编辑:
再次更改了表达式-该表达式还需要能够解析通配符mimes,例如
text/*
.
因此,表达式现在变成:
(?:\G\s?,\s?|^)(\w+|\*)\/(\w+|\*)(?:\+(\w+))?|(?<!^)\G(?:\s?;\s?(\w+)=([\w\.]+))