Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
857 views
in Technique[技术] by (71.8m points)

regex - PHP: preg_replace (x) occurrence?

I asked a similar question recently, but didn't get a clear answer because I was too specific. This one is more broad.

Does anyone know how to replace an (x) occurrence in a regex pattern?

Example: Lets say I wanted to replace the 5th occurrence of the regex pattern in a string. How would I do that?

Here is the pattern: preg_replace('/{(.*?)|:(.*?)}/', 'replacement', $this->source);

@anubhava REQUESTED SAMPLE CODE (last function doesn't work):


$sample = 'blah asada asdas  {load|:title} steve jobs {load|:css} windows apple ';


$syntax = new syntax();
$syntax->parse($sample);


class syntax {

    protected $source;
    protected $i;
    protected $r;

        // parse source
    public function parse($source) {
                // set source to protected class var
        $this->source = $source;

        // match all occurrences for regex and run loop
        $output = array();
        preg_match_all('/{(.*?)|:(.*?)}/', $this->source, $output);

                // run loop
        $i = 0;
        foreach($output[0] as $key):
            // perform run function for each occurrence, send first match before |: and second match after |:
            $this->run($output[1][$i], $output[2][$i], $i);

            $i++;
        endforeach;

        echo $this->source;

    }

        // run function
    public function run($m, $p, $i) {
                // if method is load perform actions and run inject
        switch($m):

            case 'load':
                $this->inject($i, 'content');
            break;

        endswitch;

    }

        // this function should inject the modified data, but I'm still working on this.
    private function inject($i, $r) {

          $output = preg_replace('/{(.*?)|:(.*?)}/', $r, $this->source);

    }


}


See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You're misunderstanding regular expressions: they're stateless, have no memory, and no ability to count, nothing, so you can't know that a match is the x'th match in a string - the regex engine doesn't have a clue. You can't do this kind of thing with a regex for the same reason as it's not possible to write a regex to see if a string has balanced brackets: the problem requires a memory, which, by definition, regexes do not have.

However, a regex engine can tell you all the matches, so you're better off using preg_match() to get a list of matches, and then modify the string using that information yourself.

Update: is this closer to what you're thinking of?

<?php
class Parser {

    private $i;

    public function parse($source) {
        $this->i = 0;
        return preg_replace_callback('/{(.*?)|:(.*?)}/', array($this, 'on_match'), $source);
    }

    private function on_match($m) {
        $this->i++;

        // Do what you processing you need on the match.
        print_r(array('m' => $m, 'i' => $this->i));

        // Return what you want the replacement to be.
        return $m[0] . '=>' . $this->i;
    }
}

$sample = 'blah asada asdas  {load|:title} steve jobs {load|:css} windows apple ';
$parse = new Parser();
$result = $parse->parse($sample);
echo "Result is: [$result]
";

Which gives...

Array
(
    [m] => Array
        (
            [0] => {load|:title}
            [1] => load
            [2] => title
        )

    [i] => 1
)
Array
(
    [m] => Array
        (
            [0] => {load|:css}
            [1] => load
            [2] => css
        )

    [i] => 2
)
Result is: [blah asada asdas  {load|:title}=>1 steve jobs {load|:css}=>2 windows apple ]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...