Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 用preg_Replace_回调替换preg_Replace()e修饰符_Php_Regex_Preg Replace_Preg Replace Callback - Fatal编程技术网

Php 用preg_Replace_回调替换preg_Replace()e修饰符

Php 用preg_Replace_回调替换preg_Replace()e修饰符,php,regex,preg-replace,preg-replace-callback,Php,Regex,Preg Replace,Preg Replace Callback,我对正则表达式很在行。我正在尝试替换这个: public static function camelize($word) { return preg_replace('/(^|_)([a-z])/e', 'strtoupper("\\2")', $word); } 使用preg_将_回调替换为匿名函数。我不明白\\2正在做什么。或者就这一点而言,preg_replace_回调是如何工作的 实现这一点的正确代码是什么?在正则表达式中,可以用括号捕获匹配字符串的一部分;在本例中,您将捕获匹配

我对正则表达式很在行。我正在尝试替换这个:

public static function camelize($word) {
   return preg_replace('/(^|_)([a-z])/e', 'strtoupper("\\2")', $word);
}
使用preg_将_回调替换为匿名函数。我不明白\\2正在做什么。或者就这一点而言,preg_replace_回调是如何工作的


实现这一点的正确代码是什么?

在正则表达式中,可以用括号捕获匹配字符串的一部分;在本例中,您将捕获匹配的^ |和[a-z]部分。这些都是从1开始编号的,所以您有后面的引用1和2。匹配0是整个匹配字符串

/e修饰符接受一个替换字符串,并用适当的反向引用替换反斜杠后面的数字,例如.\1-但由于您位于字符串内部,因此需要转义反斜杠,因此得到“\\1”。然后它有效地运行eval来运行结果字符串,就像它是PHP代码一样,这就是为什么它被弃用的原因,因为它很容易以不安全的方式使用eval

preg_replace_回调函数取而代之的是一个回调函数,并向其传递一个包含匹配的反向引用的数组。因此,在编写“\\1”的地方,您可以访问该参数的元素1,例如,如果您有一个匿名函数,其形式为$matches{…},则该函数中的第一个反向引用是$matches[1]

所以a/e参数

'do_stuff(\\1) . "and" . do_stuff(\\2)'
可能会成为一个

function($m) { return do_stuff($m[1]) . "and" . do_stuff($m[2]); }
还是你的情况

'strtoupper("\\2")'
可能成为

function($m) { return strtoupper($m[2]); }
请注意,$m和$matches不是神奇的名称,它们只是我在声明回调函数时给出的参数名。另外,您不必传递匿名函数,它可以是作为字符串的函数名,也可以是数组$object$方法的形式,例如

与任何函数一样,默认情况下,您不能从周围范围访问回调之外的变量。使用匿名函数时,可以使用use关键字导入需要访问的变量。e、 如果旧的论点是正确的

'do_stuff(\\1, $foo)'
那么新的回调可能看起来像

function($m) use ($foo) { return do_stuff($m[1], $foo); }
戈查斯 使用preg_replace_回调代替正则表达式上的/e修饰符,因此需要从模式参数中删除该标志。所以像/blah.*blah/mei这样的模式将变成/blah.*blah/mi。 e修饰符在参数内部使用了addslashes的一个变体,因此一些替换使用了stripslashes来删除它;在大多数情况下,您可能希望从新回调中删除对stripslashes的调用。 一般不应使用标志e或eval

你也可以使用

preg_用eval支架更换垫片 这是非常不可取的。但是,如果您不是程序员,或者确实喜欢糟糕的代码,您可以使用替换preg_replace函数暂时保持/e标志工作

\n; } 请记住,仅仅复制和粘贴并不是编程。您必须使生成的代码适应实际的输入/输出变量名或使用上下文

具体来说,如果在if中使用了前一个preg_replace调用,$OUTPUT=赋值必须取消。 但最好保留临时变量或多行代码块结构。 替换表达式可能需要更多的可读性改进或返工

例如,在文字表达式中,斜杠经常变得多余。 变量范围查找需要回调的use或全局引用。 不均匀的引号括起-$1-$2捕获引用将在语法上被转换成-$m[1]-$m[2]而终止。
代码输出仅仅是一个起点。是的,作为一个在线工具,这会更有用。这种代码重写方法“编辑、运行、编辑、编辑”有些不切实际。然而,对于那些习惯于以任务为中心的编码的人来说,它可能更容易接近——更多的步骤,更多的发现。因此,这个替代方案可能会抑制一些重复的问题。

e修饰符从PHP5.5开始使用。0@HamZaDzCyberDeV我知道。这就是我想用preg_replace_callback替换它的原因之一。有一个手册页。和\\2将成为所述回调中的$matches[2]。或者说,你到底对哪一部分感到困惑?@mario-ahh,$matches[2]就是我所需要的。我仍然不明白它是如何工作的,但它确实如此。如果你把它放在一个答案中,我会把它标记为解决了问题。请不要使用create_函数,它只是eval的另一个包装。您应该使用适当的匿名函数,除非您出于某种原因被困在PHP5.2中。
function($m) use ($foo) { return do_stuff($m[1], $foo); }
pattern('(^|_)([a-z])')->replace($word)->by()->group(2)->callback('strtoupper');
/**
 * Can be used as a stopgap shim for preg_replace() calls with /e flag.
 * Is likely to fail for more complex string munging expressions. And
 * very obviously won't help with local-scope variable expressions.
 *
 * @license: CC-BY-*.*-comment-must-be-retained
 * @security: Provides `eval` support for replacement patterns. Which
 *   poses troubles for user-supplied input when paired with overly
 *   generic placeholders. This variant is only slightly stricter than
 *   the C implementation, but still susceptible to varexpression, quote
 *   breakouts and mundane exploits from unquoted capture placeholders.
 * @url: https://stackoverflow.com/q/15454220
 */
function preg_replace_eval($pattern, $replacement, $subject, $limit=-1) {
    # strip /e flag
    $pattern = preg_replace('/(\W[a-df-z]*)e([a-df-z]*)$/i', '$1$2', $pattern);
    # warn about most blatant misuses at least
    if (preg_match('/\(\.[+*]/', $pattern)) {
        trigger_error("preg_replace_eval(): regex contains (.*) or (.+) placeholders, which easily causes security issues for unconstrained/user input in the replacement expression. Transform your code to use preg_replace_callback() with a sane replacement callback!");
    }
    # run preg_replace with eval-callback
    return preg_replace_callback(
        $pattern,
        function ($matches) use ($replacement) {
            # substitute $1/$2/… with literals from $matches[]
            $repl = preg_replace_callback(
                '/(?<!\\\\)(?:[$]|\\\\)(\d+)/',
                function ($m) use ($matches) {
                    if (!isset($matches[$m[1]])) { trigger_error("No capture group for '$m[0]' eval placeholder"); }
                    return addcslashes($matches[$m[1]], '\"\'\`\$\\\0'); # additionally escapes '$' and backticks
                },
                $replacement
            );
            # run the replacement expression
            return eval("return $repl;");
        },
        $subject,
        $limit
    );
}
/**
 * Use once to generate a crude preg_replace_callback() substitution. Might often
 * require additional changes in the `return …;` expression. You'll also have to
 * refit the variable names for input/output obviously.
 *
 * >>>  preg_replace_eval_replacement("/\w+/", 'strtopupper("$1")', $ignored);
 */
function preg_replace_eval_replacement($pattern, $replacement, $subjectvar="IGNORED") {
    $pattern = preg_replace('/(\W[a-df-z]*)e([a-df-z]*)$/i', '$1$2', $pattern);
    $replacement = preg_replace_callback('/[\'\"]?(?<!\\\\)(?:[$]|\\\\)(\d+)[\'\"]?/', function ($m) { return "\$m[{$m[1]}]"; }, $replacement);
    $ve = "var_export";
    $bt = debug_backtrace(0, 1)[0];
    print "<pre><code>
    #----------------------------------------------------
    # replace preg_*() call in '$bt[file]' line $bt[line] with:
    #----------------------------------------------------
    \$OUTPUT_VAR = preg_replace_callback(
        {$ve($pattern, TRUE)},
        function (\$m) {
            return {$replacement};
        },
        \$YOUR_INPUT_VARIABLE_GOES_HERE
    )
    #----------------------------------------------------
    </code></pre>\n";
}