我几乎没有regx的经验,但我会尽力而为。
我有一个这样的字符串:
$fString = "Name=Sök,Value=2,Title=Combine me,Options=[Item1=1,Item2=2,Item3=3]";
我希望得到一个如下所示的数组:
Array[0] = "Name=Sök"
Array[1] = "Value=2"
Array[2] = "Title=Combine me"
Array[3] = "Options=[Item1=1,Item2=2,Item3=3]"
到目前为止我设法做的是:
preg_match_all("/[^,]*[\w\d]*=[^,]*/",$fString,$Data);
但我无法弄清楚如何修复最后一个“选项”。
Array ( [0] => Array ( [0] => Name=S�k [1] => Value=2 [2] => Title=Combine me [3] => Options=[Item1=1 [4] => Item2=2 [5] => Item3=3] ) )
...为什么结果是一个数组内的数组?!?
[编辑]
我想我需要解释一下我在这里想做什么的整个想法,我不确定我是否已经走上正轨了。
我创建了一些类,我将所有“持久”变量存储在一个数组中。我有一个序列化这个数组的函数,所以我可以存储在数据库中。
我知道所有关于serialize()函数的信息,但是我正在进行一些过滤,所以我不能按原样使用它,而且我也希望手动编辑更具可读性。此数组可以在其中包含需要保留的嵌套数组。当我从数据库中读回所有内容时,必须再次创建原始数组。
我已经使用了eval()命令,但由于“或”字符打破了主外部字符串,我遇到了嵌套数组的麻烦。所以这种方法是尝试序列化所有没有嵌套字符串的内容需要保留。
所以,如果我能用preg_match_all解决嵌套数据,我就在那里,否则我需要提出另一个解决方案。
我想数据也需要转义,例如,和[]
答案 0 :(得分:2)
(\w+)=(\[[^\]]+\]|[^,]+)
这打破了:
(\w+) # a word (store in match group 1)
= # the "=" character
( # begin match group 2
\[ # a "[" character
[^\]]+ # anything but "]" character
\] # a "]" character
| # or...
[^,]+ # anything but a comma
) # end match group 1
申请preg_match_all()
:
$fString = "Name=Sök,Value=2,Title=Combine me,Options=[Item1=1,Item2=2,Item3=3]";
$matches = array();
preg_match_all("/(\\w+)=(\\[[^\\]]+\\]|[^,]+)/", $fString, $matches);
这会产生比你想要的更详细的东西:
Array
(
[0] => Array
(
[0] => Name=Sök
[1] => Value=2
[2] => Title=Combine me
[3] => Options=[Item1=1,Item2=2,Item3=3]
)
[1] => Array
(
[0] => Name
[1] => Value
[2] => Title
[3] => Options
)
[2] => Array
(
[0] => Sök
[1] => 2
[2] => Combine me
[3] => [Item1=1,Item2=2,Item3=3]
)
)
$result[0]
就是你想要的。 $result[1]
和$result[2]
分别是属性名称和值,这使您可以立即使用它们,而无需执行额外的步骤,将"Options=[Item1=1,Item2=2,Item3=3]"
之类的内容拆分为正确的=
。
答案 1 :(得分:2)
这是一个基本上可以满足你需要的功能:
function explode_me($str) {
$a = array();
$v = "";
$ignore = false;
for ($i = 0; $i < strlen($str); $i++) {
if ($str[$i] == ',' && !$ignore) {
$a[] = $v;
$v = "";
}
else if ($str[$i] == '[' && !$ignore) {
$ignore = true;
$v .= $str[$i];
}
else if ($str[$i] == ']' && $ignore) {
$ignore = false;
$v .= $str[$i];
}
else {
$v .= $str[$i];
}
}
$a[] = $v;
return $a;
}
测试它:
$str = "Name=Sök,Value=2,Title=Combine me,Options=[Item1=1,Item2=2,Item3=3]";
$a = explode_me($str);
print_r($a);
打印:
Array
(
[0] => Name=Sök
[1] => Value=2
[2] => Title=Combine me
[3] => Options=[Item1=1,Item2=2,Item3=3]
)
答案 2 :(得分:1)
如果您可以更改项目之间的分隔符(其中Item1 = 1,Item2 = 2,Item3 = 3,类似于Item1 = 1 | Item2 = 2 | Item3 = 3),您可以轻松使用{{1}将字符串转换为数组。
我也可以提供这段代码来改变分隔符,因为我没有使用正则表达式的经验:
explode(',',$fString)
$newstr = str_replace(',Item','|Item',$fString);
$newarray = explode(',',$newstr);
将如下所示:
$newarray
答案 3 :(得分:1)
这个问题比正则表达式提取更适合解析。您可以将特殊情况分开以使其正常工作:
preg_match_all("/(\w+)=( \w[^,]+ | \[[^\]]+\] )/x", $str, $m);
$things = array_combine($m[1], $m[2]);
会给你一个PHP变量(但是你可以访问$ m [0]来获取未解析的字符串):
[Name] => Sök
[Title] => Combine me
[Options] => [Item1=1,Item2=2,Item3=3]
您可以在Options
上重新应用该功能以使其爆炸。
再次诀窍是区分\w
以字母开头的任何内容和\[...\]
个封闭选项。在那里你必须让它匹配^]
所有非关闭括号,就是这样。
答案 4 :(得分:1)
所以,这是另一种方法。它是嵌套结构的迷你解析器。如果需要转义码,请调整正则表达式。
function parse(&$s) {
while (strlen($s) && preg_match("/^(.*?)([=,\[\]])/", $s, $m)) {
$s = substr($s, 1 + strlen($m[1]));
switch ($m[2]) {
case "=":
$key = $m[1];
break;
case ",":
if (!isset($r[$key])) {
$r[$key] = $m[1];
}
break;
case "[":
$r[$key] = parse($s);
break;
case "]":
return $r;
}
}
if ($s) { $r[$key] = $s; } // remainder
return $r;
}