PHP preg_match_all表达式

时间:2011-01-11 10:18:24

标签: php regex arrays preg-match-all

我几乎没有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解决嵌套数据,我就在那里,否则我需要提出另一个解决方案。

我想数据也需要转义,例如,和[]

5 个答案:

答案 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;
}