匹配模式,但不返回全部模式



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

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 会导致 :column_32变成 :Test_32 等。

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

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

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

这可能有点麻烦,但是您如何按密钥长度从最长到最短对数组进行排序。然后,任何可以作为另一个键的子字符串的键都将在其包含字符串之后进行检查。因此,您可以像这样对数组进行重新排序:

$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");

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

你为什么不试着找到标识符呢?例如,搜索:column_347就可以了。您可能想在占位符后搜索单词边界,以告诉您的正则表达式"如果这个(例如列)不是整个单词,请不要停止。

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

这并不能回答您的正则表达式问题,但无论如何我都想提供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 都提供了合理的建议。

最新更新