3

我对正则表达式很陌生。假设我有一个这样的字符串:

UPDATE table_name SET column = :column WHERE column IN(:column_32, :column_34, :column_347)

然后假设我有一个数组:

$arr = array(
    'column' => 'Test',
    'column_32' => 'Tester',
    'column_34' => 'Faux data',
    'column_347' => 'Column data'
);

我想要做的是用数组中的相应值替换占位符(:column,:column_32 等)。问题是,str_replace 不会削减它,因为将 :column 替换为 'Test' 将导致 :column_32 变为 :Test_32 等。

所以,我开始写一些自定义的正则表达式。这是我一直在运行的测试脚本:

foreach($arr as $k => $v){
    var_dump(preg_match_all('(:'.$v.'[^_])', $str, $matches));
}

它匹配正确的字符串。问题是,它还返回 "," 和 ")" 作为匹配的一部分。我在这里忽略了什么吗?

4

3 回答 3

3

这可能有点小技巧,但是您如何按从最长到最短的键长度对数组进行排序。然后,任何可以是另一个键的子字符串的键都将在其包含的字符串之后进行检查。所以你像这样重新排列你的数组:

$arr = array(
    'column_347' => 'Column data'
    'column_32' => 'Tester',
    'column_34' => 'Faux data',
    'column' => 'Test',
);

当然,您也可以自动执行此操作。从 PHP 5.3.0 开始,如下所示:

uksort($arr, function($a, $b) {
    if(strlen($a) > strlen($b))
        return -1;
    else
        return 0;
});

在 5.3.0 以下,您可以使用它(从 PHP 4.0.1 开始):

uksort($arr, create_function('$a, $b', '
    if(strlen($a) > strlen($b))
        return -1;
    else
        return 0;
'));

或者(如果您不能使用漂亮的匿名函数语法,或者如果您在 4.0.1 之前使用 PHP,这可能更可取):

function compare($a, $b) {
    if(strlen($a) > strlen($b))
        return -1;
    else
        return 0;
}

uksort($arr, "compare");
于 2012-11-26T15:49:35.233 回答
2

基本上,您要避免_关键字后面的所有非字符。[^_]在你的变量意味着“找到一个不是下划线的单个字符”之后,因此你的正则表达式正确地抓住了逗号和右括号。

为什么不尝试查找标识符?例如搜索:column_347就可以了。您可能希望在占位符之后搜索单词边界,以告诉您的正则表达式“如果此(例如列)不是一个完整的单词,请不要停止。

这是通过替换[^_]单词\b边界来获得的。此链接显示了它是如何工作的,请注意正则表达式仅匹配第一个“列”

于 2012-11-26T15:51:46.577 回答
2

这不能回答您的正则表达式问题,但我还是想提供PDO实现:

<?php

    $sql = 'UPDATE table_name SET column = :column WHERE column IN(:column_32, :column_34, :column_347)'

    $arr = array(
        'column' => 'Test',
        'column_32' => 'Tester',
        'column_34' => 'Faux data',
        'column_347' => 'Column data'
    );

    $sth = $dbh->prepare($sql);

    foreach ($arr as $k => $v) {
        $sth->bindParam(':' . $k, $v);
    }

    $sth->execute();

?>

如果您正在使用其他人的代码并且不知道PDO,那么这可能是正确的方法,原因有很多(包括防止注入攻击)。但是,如果您知道PDO并希望有一个替代的、基于正则表达式的实现,那么@m.buettner 和@Gabber 都会提供合理的建议。

于 2012-11-26T16:00:43.700 回答