0

I have input strings like

Wires: 8 Pairs: 4

The both numbers may be different for different strings

So, only dividing and only numbers can be different

I need to get the output result like

Wires: 2 Pairs: 4

That is the number of wires should become the result of diving the first number by the second one

Here is my working PHP code:

<?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;

But the point is, both patterns and replacements should be stored in and loaded from external JSON file as strings.

The patterns are working if I store them in the file, adding two escaping backslashes instead of one like (\\s)(\\d+)

But how to deal with the replacements?

If I try something like

<?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;

I simply get

Wires: $m[3]/$m[7] Pairs: $m[3]
stckvrw
  • 1,689
  • 18
  • 42
  • What if you go with `"Wires: {$m[3]}/{$m[7]} Pairs: {$m[3]}"`? – Randommm May 04 '23 at 11:52
  • 1
    @Randommm the output is the same as mine – stckvrw May 04 '23 at 11:56
  • We only have one primitive example. How dynamic does this need to be? Are you ever doing more than dividing two numbers? This design decision has a smell and may need a rethink. Please [edit] your question to better express how the input may vary. – mickmackusa May 04 '23 at 12:41
  • @mickmackusa Only dividing. And only numbers can be different – stckvrw May 04 '23 at 12:42
  • So the `Wires` and `Pairs` is consistent in the input strings? – mickmackusa May 04 '23 at 12:50
  • @mickmackusa Yes. Again, only numbers are different – stckvrw May 04 '23 at 12:54
  • Other pages that recommend `eval()`: [calling php function from string (with parameters)](https://stackoverflow.com/q/6237012/2943403) and [How to execute string php code to run](https://stackoverflow.com/q/45281429/2943403) and [PHP parse function call with parameters from string](https://stackoverflow.com/q/66183663/2943403) and [PHP Execute a string containing static function call](https://stackoverflow.com/q/31239955/2943403) and [PHP 7.2 - How to create anonymous function dynamically when having function body in a string](https://stackoverflow.com/q/52579112/2943403) – mickmackusa May 04 '23 at 13:24

2 Answers2

1

PHP doesn't allow you to serialize functions, so to serialize a function, you need a library such as this one: https://github.com/opis/closure

If using a library cannot be your choice, another convenient but VERY DANGEROUS way is to use eval.

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

$output = preg_replace_callback('/'.$pattern.'/',
    function($m) use ($repl) {
        return eval($repl);
    },
$input);
shingo
  • 18,436
  • 5
  • 23
  • 42
1

There is absolutely no reason to store any part of this task anywhere else because you state that only the numbers will change.

Use sprintf() to avoid quoting problems.

Code: (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
     );

Or, you can use sscanf() and printf(). Demo

sscanf($input, 'Wires: %d Pairs: %d', $wires, $pairs);
printf('Wires: %d Pairs: %d', $wires / $pairs, $pairs);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • 2
    _both patterns and replacements should be stored in and loaded from external JSON file as strings._ So I presume you can't manually write the math on our own. – nice_dev May 04 '23 at 12:35
  • 1
    mickmackusa thanks, but I need the replacement prepared outside the preg_replace_callback(). It's not a problem for me to manually write it inside – stckvrw May 04 '23 at 12:36
  • Why do you _believe_ that you require the replacement to be declared somewhere else? It is either a bad idea or you need to explain the reason for this complexity. – mickmackusa May 04 '23 at 13:08
  • @mickmackusa There are also another patterns and replacements in JSON file for preg_replace(). But yes, you're right - I can just store there numbers for my preg_replace_callback() – stckvrw May 04 '23 at 13:21
  • I suppose you could do something like https://3v4l.org/I7iXq, but I don't see the benefit. – mickmackusa May 04 '23 at 13:40