我对正则表达式很新。假设我有一个像这样的字符串:
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));
}
匹配正确的字符串。问题是,它还返回“,”和“)”作为匹配的一部分。我在这里忽略了什么吗?
答案 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都会提供合理的建议。