0

I have to modify an URL like this:

$string = "/st:1/sc:RsrlYQhSQvs=/fp:1/g:3/start:2015-07-01/end:2015-07-30";

Namely, I want to delete st:1 with a regex. I used:

preg_replace("/\/st:(.*)\//",'',$string)

but I got

end:2015-07-30

while I would like to get:

/sc:RsrlYQhSQvs=/fp:1/g:3/start:2015-07-01/end:2015-07-30

Same if I would like to delete fp:1.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
gdm
  • 7,647
  • 3
  • 41
  • 71

4 Answers4

3

You are using greedy matching with . that matches any character.

Use a more restricted pattern:

preg_replace("/\/st:[^\/]*/",'',$string)

The [^\/]* negated character class only matches 0 or more characters other than /.

Another solution would be to use lazy matching with *? quantifier, but it is not that efficient as with the negated character class.

FULL REGEX EXPLANATION:

  • \/st: - literal /st:
  • [^\/]* - 0 or more characters other than /.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
3

You can use:

$string = preg_replace('~/st:[^/]*~','',$string);

[^/]* will only match till next /

anubhava
  • 761,203
  • 64
  • 569
  • 643
1

You need to add ? in your regex:-

<?php

$string = "/st:1/sc:RsrlYQhSQvs=/fp:1/g:3/start:2015-07-01/end:2015-07-30";
echo preg_replace("/\/st:(.*?)\//",'',$string)

 ?>

Output:- https://eval.in/397658

Based on this same you can do for next things also.

Alive to die - Anant
  • 70,531
  • 10
  • 51
  • 98
  • Thankyou. And If would like to match the patter also when it happens at the hand of the string? as in /sc:r2342/st:1 – gdm Jul 13 '15 at 12:39
  • Found. /st:(.*?)\/|\/st:(.*?)$/ – gdm Jul 13 '15 at 12:48
  • 1
    As I noted in my answer, lazy matching - `.*?` - is not recommended as it impacts performance, and may overmatch. Maybe it is not the case, and more a question of style in this very case, but it is an important note. Also, I'd rather accept the correct answer that was given first. – Wiktor Stribiżew Jul 13 '15 at 12:56
0

Instead of using regex here you should make parsing utility functions for your special format string, they are simple, they don't take to long to write and they will make your life a lot easier:

function readPath($path) {
    $parameters = array();

    foreach(explode('/', $path) as $piece) {
        // Here we make sure we have something
        if ($piece == "") {
            continue;
        }

        // This here is just a fancy way of splitting the array returned
        // into two variables.
        list($key, $value) = explode(':', $piece);
        $parameters[$key] = $value;
    }

    return $parameters;
} 

function writePath($parameters) {
    $path = "";

    foreach($parameters as $key => $value) {
        $path .= "/" . implode(":", array($key, $value));
    }

    return $path;
}

Now you can just work on it as a php array, in this case you would go:

$parameters = readPath($string);

unset($parameters['st']);

$string = writePath($parameters);

This makes for much more readable and reusable code, additionally since most of the time you are dealing with only slight variations of this format you can just change the delimiters each time or even abstract these functions to using different delimiters.


Another way to deal with this is to convert the string to conform to a normal path query, using something like:

function readPath($path) {
    return parse_str(strtr($path, "/:", "&="));
}

In your case though since you are using the "=" character in a url you would also need to url encode each value so as to not conflict with the format, this would involve similarly structured code to above though.

Jessie
  • 322
  • 3
  • 7