2011-01-11 90 views
1

我几乎没有雷克斯的经验,但尽我所能。PHP preg_match_all表达式

我有一个这样的字符串:

$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

结果总是在一个数组中。 $数据输出始终是一个多维数组,其中包含多个结果类型。 – powtac 2011-01-11 10:27:28

+0

这些值可以有逗号,例如`“Title = Combine,me”`?如果是,那么如何处理? – Tomalak 2011-01-11 10:52:12

+0

然后你需要一个迷你解析器。看看@SirDarius做了什么。你只需要一些东西来寻找最近的``,``或`[`,然后下降```或者将收集到的列表返回给`````。 – mario 2011-01-11 15:48:06

回答

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] 
) 
1

如果您可以更改项目之间的分隔符(其中它表示Item1 = 1,Item2 = 2,Item3 = 3,类似于Item1 = 1 | Item2 = 2 | Item3 = 3),您可以轻松使用explode(',',$fString)将字符串转换为数组。

我也可以提供这一段代码,这将改变分隔符,因为我有一个正则表达式的经验:

$newstr = str_replace(',Item','|Item',$fString); 
$newarray = explode(',',$newstr); 

$newarray看起来就像这样:

Array[0] = "Name=Sök" 
Array[1] = "Value=2" 
Array[2] = "Title=Combine me" 
Array[3] = "Options=[Item1=1|Item2=2|Item3=3]" 
+0

我之前也有这样的想法,但我需要能够重新将块重新包装以解开它们。 – 2011-01-11 15:20:26

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任何以字母开头的东西和\[...\]封闭的选项。在那里,你必须让它匹配^]所有非闭合括号,就是这样。

+0

谢谢,这实际上是我所瞄准的结果。只有一个问题:当我迭代参数(首先删除[...])时,“Item1 = 1,Item2 = 2,Item3 = 3”失败,因为没有数字匹配。我试图把\ d,但不能使它工作。 Furter我需要能够嵌套块,如Controls = [Options = [Item1 = 1,Item2 = 2],Name = Foo]也许这不是正确的方法?!? – 2011-01-11 15:18:32

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

所以,这里是另一种方法。这是嵌套结构的一个迷你解析器。如果您需要转义码,请调整正则表达式。

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