skip to Main Content

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]

2

Answers


  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);
    
    Login or Signup to reply.
  2. 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);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search