替换字符串中的PHP preg_引号
我使用preg_replace,希望在替换字符串中包含url。如何引用该字符串?似乎preg_quote仅用于搜索模式替换字符串中的PHP preg_引号,php,regex,preg-replace,Php,Regex,Preg Replace,我使用preg_replace,希望在替换字符串中包含url。如何引用该字符串?似乎preg_quote仅用于搜索模式 $replace = '\1'.addslashes($url).'\3'.addslashes($title).'\4'; 需要逃跑 addslashes不够 preg_quote逃逸太多 看 正如Mario所评论的,您可以使用addcslashes($str,\\$”)不幸的是,没有通用的方法可以做到这一点,但在大多数情况下addslashes应该足够了 为了最大限度的安
$replace = '\1'.addslashes($url).'\3'.addslashes($title).'\4';
addslashes
不够preg_quote
逃逸太多正如Mario所评论的,您可以使用
addcslashes($str,\\$”)
不幸的是,没有通用的方法可以做到这一点,但在大多数情况下addslashes
应该足够了
为了最大限度的安全,您可以使用${1}
语法。例如
$replace = '${1}'.addslashes($url).'${3}'.addslashes($title).'${4}';
如果你真的想完全防弹,使用回调替换函数。回调函数返回的字符串完全按原样使用,因此您不必担心将替换语法与普通文本混合使用
带有preg\u replace\u callback()
的示例:
您没有提供示例,所以我自己编译了一个。我提出的工作解决方案是使用一个简单的回调函数:
$url = 'http://example.com/';
$title = 'Make it Complex \4';
$subject = 'Call \\4 " $me an url';
$pattern = '/(.*)an()( )(url)/';
$replace = function($m) use ($url, $title)
{
return "$m[1]$url$m[3]$title$m[4]";
};
$result = preg_replace_callback($pattern, $replace, $subject);
结果:
Call \4 " $me http://example.com/ Make it Complex \4url
回调函数是一个所谓的函数,它可以方便地就地编辑代码
如果您更经常地需要它,您可以将它放入您自己的函数中,可能是为了使它更可重用。您甚至可以走到这一步,创建自己的模式来替换子组匹配项和变量。例如,{\1}
代表子模式1匹配,{$2}
代表第二个变量。将其包装为自己的函数:
$patternf = function()
{
$values = func_get_args();
$mask = $values ? array_shift($values) : NULL;
return function($matches) use ($mask, $values)
{
$parts = preg_split('/({[\\\\\\$][0-9]{1,3}})/', $mask, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as &$part)
if (preg_match('/^{([\\\\\\$])([0-9]{1,3})}$/', $part, $p))
$part = $p[1] == '\\' ? $matches[(int)$p[2]] : $values[$p[2]-1];
return implode('', $parts);
};
};
function preg_replace_subst($pattern, $replace, $subject)
{
$values = func_get_args();
$pattern = array_shift($values);
$mask = array_shift($values);
$subject = array_shift($values);
$callback = function($matches) use ($mask, $values)
{
$parts = preg_split('/({[\\\\\\$][0-9]{1,3}})/', $mask, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as &$part)
if (preg_match('/^{([\\\\\\$])([0-9]{1,3})}$/', $part, $p))
$part = $p[1] == '\\' ? $matches[(int)$p[2]] : $values[$p[2]-1];
return implode('', $parts);
};
return preg_replace_callback($pattern, $callback, $subject);
}
将使您的更换更加方便:
$replace = $patternf('{\1}{$1}{\3}{$2}{\4}', $url, $title);
$result = preg_replace_callback($pattern, $replace, $subject);
。将其包装为自己的函数:
$patternf = function()
{
$values = func_get_args();
$mask = $values ? array_shift($values) : NULL;
return function($matches) use ($mask, $values)
{
$parts = preg_split('/({[\\\\\\$][0-9]{1,3}})/', $mask, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as &$part)
if (preg_match('/^{([\\\\\\$])([0-9]{1,3})}$/', $part, $p))
$part = $p[1] == '\\' ? $matches[(int)$p[2]] : $values[$p[2]-1];
return implode('', $parts);
};
};
function preg_replace_subst($pattern, $replace, $subject)
{
$values = func_get_args();
$pattern = array_shift($values);
$mask = array_shift($values);
$subject = array_shift($values);
$callback = function($matches) use ($mask, $values)
{
$parts = preg_split('/({[\\\\\\$][0-9]{1,3}})/', $mask, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach($parts as &$part)
if (preg_match('/^{([\\\\\\$])([0-9]{1,3})}$/', $part, $p))
$part = $p[1] == '\\' ? $matches[(int)$p[2]] : $values[$p[2]-1];
return implode('', $parts);
};
return preg_replace_callback($pattern, $callback, $subject);
}
将提供一个简单的界面:
$url = 'http://example.com/';
$title = 'Make it Complex \4';
$subject = 'Call \\4 " $me an url';
$pattern = '/(.*)an()( )(url)/';
$replace = '{\1}{$1}{\3}{$2}{\4}';
$result = preg_replace_subst($pattern, $replace, $subject, $url, $title);
但是对于许多替换变量,应该可以将它们作为数组传递,否则可能会有点长
将e
修饰符与preg\u replace
一起使用(以及它不起作用的原因)
使用e
修饰符时,将替换替换字符串中的匹配项,然后对其进行求值。由于没有转义其他变量,匹配会干扰PHP变量替换,这是危险的:
$url = 'http://example.com/';
$title = 'Make it Complex \4';
$subject = 'Call me an url.';
$pattern = '/(.*)an()( )(url)/e';
$replace = '"$1{$url}$3{$title}$4"';
$result = preg_replace($pattern, $replace, $subject);
产出:
Call me http://example.com/ Make it Complex \4url.
如前所述,第一个e
-修饰符示例被破坏,因为$
不会在$subject
中获得转义,因此PHP会查找未设置的变量。那也很危险。我提出了一个变体,它解决了这个问题,但不能处理主题中的双引号:
$url = 'http://example.com/';
$title = 'Make it Complex \4';
$subject = 'Call \\4 " $me an url';
$pattern = '/(.*)an()( )(url)/e';
$replace = "'\$1'.\$url.'\$3'.\$title.'$4'";
输出:
Call \4 \" $me http://example.com/ Make it Complex \4url
^ problem, not in input.
因此,这并不是很简单,这就是它需要回调函数的原因,因为它可以不带引号地获取匹配的子模式。为了让人清楚地看到,在
preg\u replace()
的$replacement
参数中,有一种方法可以避免任何潜在的反向引用,请使用一个函数:
$url = 'http://example.com/';
$title = 'Make it Complex \4';
$subject = 'Call \\4 " $me an url';
$pattern = '/(.*)an()( )(url)/';
$replace = function($m) use ($url, $title)
{
return "$m[1]$url$m[3]$title$m[4]";
};
$result = preg_replace_callback($pattern, $replace, $subject);
function preg\u quote\u replacement($input){
返回addcslashes($input,\\$);
}
就OP而言:
$subject=preg\u replace(
美元模式,
“\1”.preg\u quote\u replacement($url)。”\3.preg\u quote\u replacement($title)。“\4”,
$subject
);
您应该使用。它的工作原理类似于SQL中的预处理语句:
Pattern::inject("\1@url\2@url\3", ['url' => $input]);
你想做什么?replace字符串没有通过正则表达式引擎,因此不需要转义。任何反向引用都应该由
$1
、$2
等引用。您可以在问题中添加更多的示例,以便清楚地了解您的操作。@hakre,显然OP想知道如何正确地转义preg_replace
中的替换字符串,以便替换内容与字符串中的原始内容完全相同(无论内容如何)。您还想知道什么?@Qtax:What is$subject
?What is$url
?What is$title
?仅是基础知识,问题并不清楚,最好根据问题给出示例。为了正确地转义$subject
中的匹配项以及变量值,我建议这是一个解决替换之前应用的任何转义函数的缺陷的答案(即双重转义问题)这似乎是一个很好的解决方案。知道如何将其他变量(如url+标题)传递给回调函数吗?使用方法而不是函数作为回调函数,并将所需的额外变量作为对象的属性。然后将回调函数提供给preg\u replace\u callback()
likearray($callbackobj,'callbackmethodname')
@Tike:您也可以使用带有/e
表达式的惰性版本作为替换字符串,将它们从本地范围中提取出来。@Tike:--好的,现在我看了一下,它实际上很糟糕。但这将是回调方法的捷径。这也是一个很好的解决方案。我会将其用于简单或一次性代码,而将preg\u replace\u callback
用于更复杂的替换或需要维护一段时间的代码的方法回调。实际上,我刚刚看到了我的代码如果$subject
包含$
,则会被破坏。我在做一点手脚,我写的关于get通过正则表达式转义的内容不包括$
。哦,我没听清楚。多么不幸:(这是PHP5.3,是的。这里有文档记录:。当一个简单的20字符解决方案(addcslashes
)时,为什么会发生这一切完美地工作?我错过了什么?