匹配键值对的正则表达式,其中值在引号或撇号中


Regular expression to match key-value pairs where value is in quotes or apostrophes

我试图在接下来的2周内完成一个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);

用匹配数组填充$result$result[n]将包含n匹配的详细信息,其中

  • $result[n][0]是整个匹配
  • $result[n][1]包含关键字
  • $result[n][2]包含值(包括引号)
编辑:

要匹配没有引号的值部分,无论使用哪种引号,您都需要一个稍微复杂一点的正则表达式,它使用正向向前看断言:

('w+)'s*='s*(["'])((?:(?!'2).)*)'2
PHP:

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]: value

解释:

(["'])    # 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.

与Tim Pietzcker的方式有点不同:

preg_match_all('/('w+)'s*='s*(?|"([^"]*)"|''([^'']*)'')/', $subject, $result, PREG_SET_ORDER);

然后是$result[n][2],它包含没有引号的值。

如何

您可以根据需要使用反向引用,参见以下模式:

/'b('w+)'s*='s*('|'")(.*)'2/U

'b是字边界,('w)捕获键,后跟=,(捕获的)撇号或引号,后跟'2,这是第二个捕获的括号(撇号或引号)。U修饰符表示非贪婪求值。

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

输出:

$arrayName["KeyName1"] = "KeyName1"
$arrayName["KeyName2"] = "KeyName2"

我希望你的意思是:

$arrayName["KeyName1"] = "KeyValue1"
$arrayName["KeyName2"] = "KeyValue2"

function paramStringToArray($string) {
    $array = array_filter(explode(' ', $string));
    $result = array();
    foreach($array as $value) {
    $data  = explode('=', $value);
        $data[1] = trim($data[1],'"');
        $data[1] = trim($data[1],'''');
        $result[$data[0]] = $data[1];
    }
    return $result;
}
$string = 'KeyName1="KeyValue1" KeyName2=''KeyValue2''';
echo '<pre>';
var_dump(paramStringToArray($string));
echo '</pre>';
输出:

array(2) {
  ["KeyName1"]=> "KeyValue1"
  ["KeyName2"]=> "KeyValue2"
}