4

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

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

KeyName1="KeyValue1" KeyName2='KeyValue2'

单个字符串中可能有任意数量的键值对,并且值可以由一个字符串中的任意组合的单引号'或双引号"分隔(但它们始终是分隔的)。

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

键值对之间可以有任意数量的空格,键名称和等号以及等号和开始键值的引号字符之间可以有任意数量的空格。

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

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

等等

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

4

4 回答 4

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

编辑:

要匹配不带引号的值部分,无论使用哪种引号,您都需要一个稍微复杂一些的正则表达式,它使用积极的前瞻断言

(\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]: 价值

解释:

(["'])    # 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.
于 2013-06-09T08:09:15.660 回答
2

Tim Pietzcker 方式的一个小变种:

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

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

于 2013-06-09T08:43:14.743 回答
1

如何

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

/\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
)
于 2013-06-09T08:21:35.927 回答
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"
}
于 2013-06-09T08:21:26.147 回答