匹配模式,但不返回所有

时间:2012-11-26 15:37:33

标签: php regex

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

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不会将其切换为替换:带有'Test'的列将导致:column_32变为:Test_32等。

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

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

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

3 个答案:

答案 0 :(得分: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");

答案 1 :(得分:2)

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

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

[^_]替换为\b这是一个词边界。 This link显示了这是如何工作的,请注意正则表达式仅匹配第一个"列"

答案 2 :(得分: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都会提供合理的建议。