php 启用preg_replace_callback()替换函数,如果它是从字符串加载的

xam8gpfp  于 2023-05-05  发布在  PHP
关注(0)|答案(2)|浏览(111)

输入字符串如下

Wires: 8 Pairs: 4

对于不同的字符串,这两个数字可能不同
所以,只有除法和只有数字可以不同
我需要得到如下的输出结果

Wires: 2 Pairs: 4

也就是电线的数量应该成为第一个数字除以第二个数字的结果
下面是我的PHP代码:

<?php
$input = 'Wires: 8 Pairs: 4';
$pattern = '(Wires:)(\s)(\d+)(\s)(Pairs:)(\s)(\d+)';

$output = preg_replace_callback('/'.$pattern.'/',
    function($m) {
        return 'Wires: '.$m[3]/$m[7].' Pairs: '.$m[7];
    },
$input);

echo $output;

但重点是,模式和替换都应该作为字符串存储在外部JSON文件中并从外部JSON文件中加载。
如果我将模式存储在文件中,并添加两个转义反斜杠(而不是像(\\s)(\\d+)那样添加一个),则模式可以正常工作
但如何处理替代品?
如果我尝试

<?php
$input = 'Wires: 8 Pairs: 4';
$pattern = '(Wires:)(\s)(\d+)(\s)(Pairs:)(\s)(\d+)';
$replacement = 'Wires: $m[3]/$m[7] Pairs: $m[3]';

$output = preg_replace_callback('/'.$pattern.'/',
    function($m) {
        global $replacement;
        return $replacement;
    },
$input);

echo $output;

我只是得到

Wires: $m[3]/$m[7] Pairs: $m[3]
8fsztsew

8fsztsew1#

PHP不允许序列化函数,所以要序列化函数,需要一个像这样的库:https://github.com/opis/closure
如果不能选择使用库,另一个方便但非常危险的方法是使用eval

$repl = 'return "Wires: ".$m[3]/$m[7]." Pairs: ".$m[7];';

$output = preg_replace_callback('/'.$pattern.'/',
    function($m) use ($repl) {
        return eval($repl);
    },
$input);
qjp7pelc

qjp7pelc2#

绝对没有理由将此任务的任何部分存储在其他任何地方,因为您声明只有数字会更改。
使用sprintf()避免引用问题。
代码:(Demo

$input = 'Wires: 8 Pairs: 4';
echo preg_replace_callback(
         '/Wires: (\d+) Pairs: (\d+)/',
         fn($m) => sprintf(
                 'Wires: %d Pairs: %d',
                 $m[1] / $m[2],
                 $m[2]
             ),
         $input
     );

或者,您可以使用sscanf()printf()Demo

sscanf($input, 'Wires: %d Pairs: %d', $wires, $pairs);
printf('Wires: %d Pairs: %d', $wires / $pairs, $pairs);

相关问题