Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/242.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 正则表达式,用于匹配值位于引号或撇号中的键值对_Php_Regex - Fatal编程技术网

Php 正则表达式,用于匹配值位于引号或撇号中的键值对

Php 正则表达式,用于匹配值位于引号或撇号中的键值对,php,regex,Php,Regex,我正试图在接下来的两周内完成一个PHP应用程序,但我无法找到解析某些属性字符串的正则表达式 我得到的随机字符串格式如下: KeyName1="KeyValue1" KeyName2='KeyValue2' 单个字符串中可能有任意数量的键值对,并且可以用一个字符串中任意组合的单引号“或双引号”来分隔值(但它们始终是分隔的) 键值可以是任意长度并包含任意字符,但双引号不能在双引号内,单引号不能在单引号内,但双引号可以在单引号内,单引号可以在双引号内 键值对之间可以有任意数量的空格,键名与等号、等号

我正试图在接下来的两周内完成一个PHP应用程序,但我无法找到解析某些属性字符串的正则表达式

我得到的随机字符串格式如下:

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);