如何(最简单的方法)转换字符串,如
oneKey="value 1" key2="value 2" anotherKey="value 3" somekey="value containing spaces"
到PHP的数组(正则表达式与否)?
我想要检索这样的值:
$myArray['key']
所以
$myArray['oneKey'] == "value"
所有密钥都不同
答案 0 :(得分:4)
匹配引用的字符串总是很棘手。
假设您的数据从不包含转义双引号(即双引号是实际值的一部分,则为简单
/(?<=^|\s)([^=]+)="([^"]*)"/
......可能会完成这项工作,但事实并非如此。所以我们需要比这更复杂一点,这就是Friedl经典的“展开循环”来拯救的地方:
/(?<=^|\s)([^=\s]+)="((?:[^\\"]|\\.)*)"/
它是如何工作的?好吧,让我们分解一下:
首先,我们从一个lookbehind开始验证匹配的开头是否以字符串的开头或空格字符开头:
(?<=^|\s)
接下来,我们查找非空白字符和非等号符号字符的任意组合(至少其中一个)。这是关键,所以我们把它放在一个捕获组中:
([^=\s]+)
接下来我们有一个文字等号和双引号:
="
接下来是“展开的循环”。这可能有点难以理解,但它的工作原理是查找任何不是引号字符或转义字符的字符(我选择反斜杠作为转义字符,但实际上你可以使用任何东西),或一个转义字符,后跟任何其他字符。这重复零次或多次。由于这是值,我们将其包装在捕获组中:
((?:[^\\"]|\\.)*)
然后我们简单地用文字双引号结束:
"
将所有内容整合到PHP代码中,您就会得到类似的内容:
$subject = 'key1="value 1" key2="value 2" key3="value 3" key4="value containing spaces"';
$expr = '/(?<=^|\\s)([^=\\s]+)="((?:[^\\\\"]|\\\\.)*)"/';
preg_match_all($expr, $subject, $matches);
$result = array();
foreach ($matches[1] as $i => $key) {
$result[$key] = $matches[2][$i];
}
但这有一个小问题。当主题字符串为:
时,请考虑what happenskey1="value\" 1"
应该好看又简单,这只是一个逃脱的引用,对吧?嗯,这是真的,上面的表达式可以轻松处理这种情况。但看看输出:
Array
(
[key1] => value\" 1
)
转义字符仍作为文字在结果字符串中。这不是我们想要的。但是上面的表达式只从主题字符串中提取相关的组件,它根本不会插入它们。为此我们需要一个单独的过程 - 但它现在只是一个简单的搜索和替换,因为我们已经将字符串分解为我们想要的标记。
所以我们只做这样的事情:
$result = preg_replace_callback('/\\\\./', function($match) {
switch ($match[0][1]) { // inspect the second character
// here we can define our special escape sequences, for example:
case 'r': return "\r";
case 'n': return "\n";
// For anything that we don't handle as a special case, we just return
// the second character in the match, effectively strip the escape
default: return $match[0][1];
}
}, $subject);
因此,当您将其与上述代码放在一起时,您会得到更像这样的内容:
$subject = 'key1="value \" 1" key2="value \n 2" key3="value 3" key4="value containing spaces"';
$matchExpr = '/(?<=^|\\s)([^=\\s]+)="((?:[^\\\\"]|\\\\.)*)"/';
$replaceExpr = '/\\\\./';
$replaceCallback = function($match) {
switch ($match[0][1]) {
case 'r': return "\r";
case 'n': return "\n";
default: return $match[0][1];
}
};
preg_match_all($matchExpr, $subject, $matches);
$result = array();
foreach ($matches[1] as $i => $key) {
$result[$key] = preg_replace_callback($replaceExpr, $replaceCallback, $matches[2][$i]);
}
答案 1 :(得分:0)
使用 preg_match_all :
尝试此正则表达式/(key[0-9]{0,})\="(.+?)"/ims
并且返回的匹配将具有键和值
答案 2 :(得分:-2)
$func = function($string) { $kv = preg_split(/="/, $string); $kv[1] = substr($kv[1], 0, length($kv[1]-1])); $myArray[$kv[0]] = $kv[1]; };
array_map($func, preg_split(/[[:space:]]+/, $string));