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

时间:2013-06-09 07:59:26

标签: php regex

我正在尝试在接下来的两周内完成一个PHP应用程序,我只是无法弄清楚正则表达式来解析一些属性字符串。

我得到的格式类似于这个字符串的随机字符串:

KeyName1="KeyValue1" KeyName2='KeyValue2'

单个字符串中可能有任意数量的键值对,并且值可以用单引号'或双引号分隔在一个字符串中string(但它们总是被分隔)。

键值可以是任何长度并包含任何字符,除了双引号不能在双引号内,单引号不能在单引号内,但双引号可以在单引号内,单引号可以是在双引号内。

键值对之间可以有任意数量的空格,键名和等号之间可以有任意数量的空格,等号和引号键可以起始键值。

我需要将字符串转换为如下所示的数组:

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

我很确定它可以用正则表达式完成,但我所有的尝试都失败了,我需要一些帮助(实际上有很多帮助:-)来完成这项工作,我希望这里有一些很棒的人可以提供帮助或至少让我开始。

4 个答案:

答案 0 :(得分:7)

当然,没问题。让我们分解一下:

\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]包含值(包括引号)

修改

要匹配没有引号的值部分,无论使用何种引号,都需要使用positive lookahead assertion的稍微复杂的正则表达式:

(\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]:keyword
  • $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.

答案 1 :(得分:2)

Tim Pietzcker的一个小变种:

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

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

答案 2 :(得分:1)

如何

您可以使用back references获取所需内容,请参阅此模式:

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

\b是字边界,(\w)捕获密钥,然后是=,(捕获)撇号或引号,后跟任何内容,直到\2,这是第二个被捕获的括号(撇号或引号)。 U修饰符表示ungreedy evaluation

示例

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

答案 3 :(得分:0)

想要输出:

$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"
}