1

好的,这真的很难用英语解释,所以我只举一个例子。

我将有以下格式的字符串:

key-value;key1-value;key2-...

我需要将数据提取为数组

array('key'=>'value','key1'=>'value1', ... )

我打算使用正则表达式来实现(大部分)这个功能,并写了这个正则表达式:

/^(\w+)-([^-;]+)(?:;(\w+)-([^-;]+))*;?$/

使用preg_match此代码:

for ($l = count($matches),$i = 1;$i<$l;$i+=2) {
    $parameters[$matches[$i]] = $matches[$i+1];
}

然而,正则表达式显然只返回 4 个反向引用——输入字符串的第一个和最后一个键值对。有没有解决的办法?我知道我可以使用正则表达式来测试字符串的正确性并explode在循环中使用 PHP 以获得完美的结果,但我真的很好奇它是否可以使用正则表达式。

简而言之,我需要key-value;通过正则表达式在字符串中捕获任意数量的这些对。

4

6 回答 6

2

您可以在提取匹配项时使用前瞻来验证输入:

/\G(?=(?:\w++-[^;-]++;?)++$)(\w++)-([^;-]++);?/

(?=(?:\w++-[^;-]++;?)++$)是验证部分。如果输入无效,匹配将立即失败,但每次应用正则表达式时仍会评估前瞻。为了保持它(以及正则表达式的其余部分)与键值对同步,我曾经\G将每个匹配锚定到前一个匹配结束的位置。

这样,如果先行第一次成功,则可以保证以后每次都成功。显然,它的效率并不高,但这可能不会成为问题——只有您的测试才能确定。

如果前瞻失败,preg_match_all()将返回零(假)。如果成功,则将在数组数组中返回匹配项:一个用于完整的键值对,一个用于键,一个用于值。

于 2010-02-11T22:09:34.827 回答
2

改为使用preg_match_all()。也许是这样的:

$matches = $parameters = array();
$input = 'key-value;key1-value1;key2-value2;key123-value123;';

preg_match_all("/(\w+)-([^-;]+)/", $input, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
   $parameters[$match[1]] = $match[2];
}

print_r($parameters);

编辑:

首先验证输入字符串是否符合模式,然后只需使用:

if (preg_match("/^((\w+)-([^-;]+);)+$/", $input) > 0) {
    /* do the preg_match_all stuff */
}       

EDIT2:最后的分号是可选的

if (preg_match("/^(\w+-[^-;]+;)*\w+-[^-;]+$/", $input) > 0) {
    /* do the preg_match_all stuff */
}       
于 2010-02-11T15:19:06.253 回答
2

正则表达式是强大的工具,但有时,它不是最好的方法。

$string = "key-value;key1-value";
$s = explode(";",$string);
foreach($s as $k){
    $e = explode("-",$k);
    $array[$e[0]]=$e[1];
}
print_r($array);
于 2010-02-11T15:15:32.470 回答
0

不会。较新的匹配会覆盖较旧的匹配。也许 的limit论点explode()在爆炸时会有所帮助。

于 2010-02-11T15:15:08.257 回答
0

这个解决方案怎么样:

$samples = array(
    "good" => "key-value;key1-value;key2-value;key5-value;key-value;",
    "bad1" => "key-value-value;key1-value;key2-value;key5-value;key-value;",
    "bad2" => "key;key1-value;key2-value;key5-value;key-value;",
    "bad3" => "k%ey;key1-value;key2-value;key5-value;key-value;"
);

foreach($samples as $name => $value) {
    if (preg_match("/^(\w+-\w+;)+$/", $value)) {
        printf("'%s' matches\n", $name);
    } else {
        printf("'%s' not matches\n", $name);
    }
}
于 2010-02-11T16:52:45.643 回答
0

我不认为你可以用一个正则表达式来验证和提取数据,因为你需要锚(^$)来验证和preg_match_all()数据,但是如果你使用锚,preg_match_all()它只会返回最后匹配的集合。

于 2010-02-11T17:41:22.503 回答