Php 正则表达式,用于匹配值位于引号或撇号中的键值对
我正试图在接下来的两周内完成一个PHP应用程序,但我无法找到解析某些属性字符串的正则表达式 我得到的随机字符串格式如下:Php 正则表达式,用于匹配值位于引号或撇号中的键值对,php,regex,Php,Regex,我正试图在接下来的两周内完成一个PHP应用程序,但我无法找到解析某些属性字符串的正则表达式 我得到的随机字符串格式如下: KeyName1="KeyValue1" KeyName2='KeyValue2' 单个字符串中可能有任意数量的键值对,并且可以用一个字符串中任意组合的单引号“或双引号”来分隔值(但它们始终是分隔的) 键值可以是任意长度并包含任意字符,但双引号不能在双引号内,单引号不能在单引号内,但双引号可以在单引号内,单引号可以在双引号内 键值对之间可以有任意数量的空格,键名与等号、等号
KeyName1="KeyValue1" KeyName2='KeyValue2'
单个字符串中可能有任意数量的键值对,并且可以用一个字符串中任意组合的单引号“或双引号”来分隔值(但它们始终是分隔的)
键值可以是任意长度并包含任意字符,但双引号不能在双引号内,单引号不能在单引号内,但双引号可以在单引号内,单引号可以在双引号内
键值对之间可以有任意数量的空格,键名与等号、等号与开始键值的引号字符之间可以有任意数量的空格
我需要将字符串转换为如下数组:
$arrayName["KeyName1"] = "KeyValue1"
$arrayName["KeyName2"] = "KeyValue2"
等等
我很确定正则表达式可以完成这项工作,但我所有的尝试都失败了,我需要一些帮助(实际上有很多帮助:-)来完成这项工作,我希望这里的一些了不起的人能够提供帮助,或者至少让我开始工作。当然,没问题。让我们来详细分析一下:
\w+\s*=\s*
匹配字母数字关键字,后跟等号(可能被空格包围)
匹配开头的双引号,后跟除另一个双引号外的任意数量的字符,然后是(结尾的)双引号
'[^']*'
对单引号字符串执行相同的操作
通过使用捕获组((…)
)和简单的替代(|
)组合,您可以
(\w+)\s*=\s*("[^"]*"|'[^']*')
在PHP中:
preg_match_all('/(\w+)\s*=\s*("[^"]*"|\'[^\']*\')/', $subject, $result, PREG_SET_ORDER);
preg_match_all('/(\w+)\s*=\s*(["\'])((?:(?!\2).)*)\2/', $subject, $result, PREG_SET_ORDER);
用匹配数组填充$result
。$result[n]
将包含第次匹配的详细信息,其中
是整个匹配项$result[n][0]
包含关键字$result[n][1]
包含值(包括引号)$result[n][2]
(["']) # Match a quote (--> group 2)
( # Match and capture --> group 3...
(?: # the following regex:
(?!\2) # As long as the next character isn't the one in group 2,
. # match it (any character)
)* # any number of times.
) # End of capturing group 3
\2 # Then match the corresponding quote character.
要匹配不带引号的值部分,无论使用哪种引号,都需要一个稍微复杂一些的正则表达式,该正则表达式使用:
在PHP中:
preg_match_all('/(\w+)\s*=\s*("[^"]*"|\'[^\']*\')/', $subject, $result, PREG_SET_ORDER);
preg_match_all('/(\w+)\s*=\s*(["\'])((?:(?!\2).)*)\2/', $subject, $result, PREG_SET_ORDER);
结果如何
:整个匹配$result[n][0]
:关键字$result[n][1]
:引用字符$result[n][2]
:值$result[n][3]
(["']) # Match a quote (--> group 2)
( # Match and capture --> group 3...
(?: # the following regex:
(?!\2) # As long as the next character isn't the one in group 2,
. # match it (any character)
)* # any number of times.
) # End of capturing group 3
\2 # Then match the corresponding quote character.
需要输出:
$arrayName["KeyName1"] = "KeyName1"
$arrayName["KeyName2"] = "KeyName2"
我希望你的意思是:
$arrayName["KeyName1"] = "KeyValue1"
$arrayName["KeyName2"] = "KeyValue2"
如何 您可以根据需要使用,请参见以下模式:
// match the key-value pairs
$text = "mykey1= \"my'value1'\" mykey2 = 'my\"value2' mykey3=\"my value3\"";
preg_match_all("/\b(\w+)\s*=\s*('|\")(.*)\\2/U",$text,$matches);
// produce result in format you need
$result = array();
for($i=0; $i<count($matches[0]); ++$i) {
$result[$matches[1][$i]] = $matches[3][$i];
}
\b
是单词边界,(\w
)捕获键,后跟=
,(捕获的)撇号或引号,后跟任何内容,直到\2
,这是第二个捕获的括号(撇号或引号)。U
修饰符的意思是
示例
Array
(
[mykey1] => my'value1'
[mykey2] => my"value2
[mykey3] => my value3
)
Tim Pietzcker way的一个小变种:
然后就有了
$result[n][2]
包含不带引号的值。谢谢Jim。你说得对,我指的是键值,并更新了帖子。我认为explode不起作用,因为键值内可能有等号。非常感谢你的帮助和你出色的表达方式,它真的有助于澄清问题,让我觉得有点傻h感谢我自己无法理解:-)我为大型公司设计和架构了多国应用程序,我设计了企业数据仓库和附带的商业智能应用程序,但正则表达式对我来说总是非常困难(它们是一种稍微简单一点的APL!)@戴维杜斯尼安:当然,不客气。我添加了一个正则表达式,它也将为您捕获不带引号的值。感谢您对它的编辑,使我不必删除它们。唯一的问题是,值现在在$result[n][2]
或$result[n][3]中
,在检查之前你不知道是哪一个…@TimPietzcker:不,因为分支重置语法(?|(..)|(..)(..)
这两个捕获组有相同的号码。简,谢谢,反向引用是另一件看起来很简单的事情,但我永远无法理解
// match the key-value pairs
$text = "mykey1= \"my'value1'\" mykey2 = 'my\"value2' mykey3=\"my value3\"";
preg_match_all("/\b(\w+)\s*=\s*('|\")(.*)\\2/U",$text,$matches);
// produce result in format you need
$result = array();
for($i=0; $i<count($matches[0]); ++$i) {
$result[$matches[1][$i]] = $matches[3][$i];
}
Array
(
[mykey1] => my'value1'
[mykey2] => my"value2
[mykey3] => my value3
)
preg_match_all('/(\w+)\s*=\s*(?|"([^"]*)"|\'([^\']*)\')/', $subject, $result, PREG_SET_ORDER);