How to replace text with a regex pattern and integrate a counter in the replacement text?

前端 未结 3 1427
孤街浪徒
孤街浪徒 2021-01-27 07:30
function parse($string){
    $counter = 0;
    
    $string = preg_replace("_\\[b\\](.*?)\\[/b\\]_si", \'\'. $counter .\'. $1&l         


        
相关标签:
3条回答
  • 2021-01-27 07:36

    Eventually solved it with the help of TiMESPLiNTER (give him the credit!), didn't know $1 didn't get brought along and that you have to call a variable $matches in the callback function and get $matches[1] instead of $1.

    $counter = 1;
    
    function parse(){
        function cb($matches){
            global $counter;
    
            return '<span class="b">'. $this->counter .'. ' . $matches[1] . '</span>';
        }
    
        $string = preg_replace_callback("_\[b\](.*?)\[/b\]_si", 'cb', $string);
    }
    
    0 讨论(0)
  • 2021-01-27 07:44

    I would solve it with a small class with the counter as property and the callback is a method of the class.

    class Increaser {
        private $counter;
    
        public function replace($string) {
            $this->counter = 0;
    
            return preg_replace_callback("_\[b\](.*?)\[/b\]_si", array($this, 'createReplacement'), $string);
        }
    
        private function createReplacement($matches) {
            ++$this->counter;
    
            return '<span class="b">'. $this->counter .'. ' . $matches[1] . '</span>';
        }
    }
    
    0 讨论(0)
  • 2021-01-27 07:47

    You don't need to declare a global "counter" variable or design a class-based workaround. You can simply use a static variable declaration inside of preg_replace_callback()'s custom function.

    Code: (Demo) -- this is the way I would code my own project

    $ubbText = <<<TEXT
    [b]Hey[/b]
    [b]Hello[/b]
    TEXT;
    
    echo preg_replace_callback(
             "~\[b](.*?)\[/b]~si",
             function ($m) {
                 static $counter = 0;
                 return '<span class="b">' . (++$counter) . '. ' . $m[1] . '</span>';
             },
             $ubbText
         );
    

    Alternatively, you could avoid the use of a static declaration and use preg_replace() because your code logic will not possibly replace replacements (an infinite loop is not possible). To be honest, I don't prefer this technique because it involves iterated preg_ function calls which make one replacement per iteration and the regex engine will need to restart from the beginning of the input string each time.

    Code: (Demo)

    $counter = 0;
    do {
        $ubbText = preg_replace(
            "~\[b](.*?)\[/b]~si",
            '<span class="b">' . (++$counter) . '. $1</span>',
             $ubbText,
             1,
             $count
         );
    } while ($count);
    echo $ubbText;
    

    Output (from both snippets):

    <span class="b">1. Hey</span>
    <span class="b">2. Hello</span>
    

    p.s. I suppose I should state for the record that your regex pattern will not favorably handle the possibility of nested tags [b] bold [b]re-bold[/b][/b]. If these types of occurrences are not possible in your application's text, then no worries. There are ways to mitigate this vulnerability, but I will not digress in this post. Search Stack Overflow for this if your application requires it.

    0 讨论(0)
提交回复
热议问题