替换字符串中的PHP preg_引号

替换字符串中的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应该足够了 为了最大限度的安

我使用preg_replace,希望在替换字符串中包含url。如何引用该字符串?似乎preg_quote仅用于搜索模式

$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()
    like
    array($callbackobj,'callbackmethodname')
    @Tike:您也可以使用带有
    /e
    表达式的惰性版本作为替换字符串,将它们从本地范围中提取出来。@Tike:--好的,现在我看了一下,它实际上很糟糕。但这将是回调方法的捷径。这也是一个很好的解决方案。我会将其用于简单或一次性代码,而将
    preg\u replace\u callback
    用于更复杂的替换或需要维护一段时间的代码的方法回调。实际上,我刚刚看到了我的代码如果
    $subject
    包含
    $
    ,则会被破坏。我在做一点手脚,我写的关于get通过正则表达式转义的内容不包括
    $
    。哦,我没听清楚。多么不幸:(这是PHP5.3,是的。这里有文档记录:。当一个简单的20字符解决方案(
    addcslashes
    )时,为什么会发生这一切完美地工作?我错过了什么?