简体   繁体   中英

PHP regex replace a word in url path

Im trying to replace a word in a url path.

Fe host.com/path/to/find should become host.com/path/to/count .

But im obviously not getting this to work.

I tried to get this group: (?:/count|/find)? at the end of the string

and all in front of it to replace it with $1/count .

But always when i try the get the part before the (?:/count|/find)? -part i mess it up.

Here is a test:

EDIT: all keys represent the test (srouce) url. And all values represent the expected result.

So if there is no "/count" on the path then it should be added.

If there is a "/count" at the end then there is nothing to do.

If there is a "/find" at the end of the path then it should change to "/count".

If there is the workd "count" somewhere in the url (like "countleaveMeAlone") it should (ofc) not be changed.

$urls = [

    'http://foo-bar.host.com/entity/to'                => 'http://foo-bar.host.com/entity/to/count',
    'http://foo-bar.host.com/entity/to/'               => 'http://foo-bar.host.com/entity/to/count',
    'http://foo-bar.host.com/entity/to/find'           => 'http://foo-bar.host.com/entity/to/count',
    'http://foo-bar.host.com/entity/to/find/'          => 'http://foo-bar.host.com/entity/to/count/',
    'http://foo-bar.host.com/entity/to/find?some=foo'  => 'http://foo-bar.host.com/entity/to/count?some=foo',
    'http://foo-bar.host.com/entity/to/find/?foo=some' => 'http://foo-bar.host.com/entity/to/count/?foo=some',

    'http://foo-bar.host.com/entity/to/count'           => 'http://foo-bar.host.com/entity/to/count',
    'http://foo-bar.host.com/entity/to/count/'          => 'http://foo-bar.host.com/entity/to/count/',
    'http://foo-bar.host.com/entity/to/count?some=foo'  => 'http://foo-bar.host.com/entity/to/count?some=foo',
    'http://foo-bar.host.com/entity/to/count/?foo=some' => 'http://foo-bar.host.com/entity/to/count/?foo=some',

    'http://foo-bar.host.com/entity/toleaveMeAlone'                 => 'http://foo-bar.host.com/entity/toleaveMeAlone',
    'http://foo-bar.host.com/entity/to/leaveMeAlone'                => 'http://foo-bar.host.com/entity/to/leaveMeAlone',
    'http://foo-bar.host.com/entity/to/countleaveMeAlone'           => 'http://foo-bar.host.com/entity/to/countleaveMeAlone',
    'http://foo-bar.host.com/entity/to/count/leaveMeAlone'          => 'http://foo-bar.host.com/entity/to/count/leaveMeAlone',
    'http://foo-bar.host.com/entity/to/countleaveMeAlone?some=foo'  => 'http://foo-bar.host.com/entity/to/countleaveMeAlone?some=foo',
    'http://foo-bar.host.com/entity/to/count/leaveMeAlone?foo=some' => 'http://foo-bar.host.com/entity/to/count/leaveMeAlone?foo=some',
];

$format = "%-70s%-70s%s\r\n";
echo sprintf($format, 'TEST', 'EXPECT', 'SUCCESS');
foreach ($urls as $url => $expect) {
    $tmp = explode('?', $url);
    $url = rtrim($tmp[0], '/');
    $query = isset($tmp[1])
        ? $tmp[1]
        : '';

    /**
     * Pattern
     * /
     *      \A                  --start string
     *      (.*)                --get all before
     *      (?:/count|/find)?   --get optional "/find" or "/count"
     *      \z                  --end string
     * /
     */
    $url = preg_replace(
        "#\A(.*)(?:/count|/find)?\z#",
        '$1/count',
        $url
    );

    $url .= strlen($query)
        ? '?' . $query
        : '';

    echo sprintf($format, $url, $expect, var_export($url === $expect, true));
}

Any help much appreciated

$urls = [
'http://foo-bar.host.com/entity/to'                => 'http://foo-bar.host.com/entity/to/count',
'http://foo-bar.host.com/entity/to/'               => 'http://foo-bar.host.com/entity/to/count',
'http://foo-bar.host.com/entity/to/find'           => 'http://foo-bar.host.com/entity/to/count',
'http://foo-bar.host.com/entity/to/find/'          => 'http://foo-bar.host.com/entity/to/count/',
'http://foo-bar.host.com/entity/to/find?some=foo'  => 'http://foo-bar.host.com/entity/to/count?some=foo',
'http://foo-bar.host.com/entity/to/find/?foo=some' => 'http://foo-bar.host.com/entity/to/count/?foo=some'];
foreach ($urls as $url => $expect) {   
$new_url = str_replace("find","count",$url);
echo $new_url."<br />";
}

Pattern: ( Pattern/Replacement Demo with Official Explanation )

~^([^?]+?)/?((?:(?:/count|leaveMeAlone)(*SKIP)(*FAIL))|(?:find/??)?)((?:(?<=find)/)?)((?:\?.*)?)$~

Layman's Breakdown:

  • ~ Starting pattern delimiter (not a slash, so slashes don't need to be escaped in the pattern)
  • ^ Match the start of the string
  • ([^?]+?) Capture one or more characters that are not a question mark (lazy/non-greedy)
  • /? Match zero or one slash
  • ( Capture...
    • (?:(?:/count|leaveMeAlone)(*SKIP)(*FAIL)) Disqualify entire string if /count or leaveMeAlone is found before ?
    • | Or
    • (?:find/??)? Optionally capture find with zero or one trailing slash (lazy)
  • ) ...end capture
  • ((?:(?<=find)/)?) Capture zero or one slash IF it is preceded by find
  • ((?:\\?.*)?) Capture the optional query string portion of the url
  • $ Match the end of the string
  • ~ Ending pattern delimiter

Code: ( Demo )

$urls = [
    'http://foo-bar.host.com/entity/to'                => 'http://foo-bar.host.com/entity/to/count',
    'http://foo-bar.host.com/entity/to/'               => 'http://foo-bar.host.com/entity/to/count',
    'http://foo-bar.host.com/entity/to/find'           => 'http://foo-bar.host.com/entity/to/count',
    'http://foo-bar.host.com/entity/to/find/'          => 'http://foo-bar.host.com/entity/to/count/',
    'http://foo-bar.host.com/entity/to/find?some=foo'  => 'http://foo-bar.host.com/entity/to/count?some=foo',
    'http://foo-bar.host.com/entity/to/find/?foo=some' => 'http://foo-bar.host.com/entity/to/count/?foo=some',

    'http://foo-bar.host.com/entity/to/count'           => 'http://foo-bar.host.com/entity/to/count',
    'http://foo-bar.host.com/entity/to/count/'          => 'http://foo-bar.host.com/entity/to/count/',
    'http://foo-bar.host.com/entity/to/count?some=foo'  => 'http://foo-bar.host.com/entity/to/count?some=foo',
    'http://foo-bar.host.com/entity/to/count/?foo=some' => 'http://foo-bar.host.com/entity/to/count/?foo=some',

    'http://foo-bar.host.com/entity/toleaveMeAlone'                 => 'http://foo-bar.host.com/entity/toleaveMeAlone',
    'http://foo-bar.host.com/entity/to/leaveMeAlone'                => 'http://foo-bar.host.com/entity/to/leaveMeAlone',
    'http://foo-bar.host.com/entity/to/countleaveMeAlone'           => 'http://foo-bar.host.com/entity/to/countleaveMeAlone',
    'http://foo-bar.host.com/entity/to/count/leaveMeAlone'          => 'http://foo-bar.host.com/entity/to/count/leaveMeAlone',
    'http://foo-bar.host.com/entity/to/countleaveMeAlone?some=foo'  => 'http://foo-bar.host.com/entity/to/countleaveMeAlone?some=foo',
    'http://foo-bar.host.com/entity/to/count/leaveMeAlone?foo=some' => 'http://foo-bar.host.com/entity/to/count/leaveMeAlone?foo=some',
];

$pattern='~^([^?]+?)/?((?:(?:/count|leaveMeAlone)(*SKIP)(*FAIL))|(?:find/??)?)((?:(?<=find)/)?)((?:\?.*)?)$~';
$replace='$1/count$3$4';
foreach($urls as $url=>$expected){
    echo "$url\n";                                   // your input
    echo preg_replace($pattern,$replace,$url),"\n";  // my output
    echo "$expected\n\n";                            // your expected output
}

Output:

http://foo-bar.host.com/entity/to
http://foo-bar.host.com/entity/to/count
http://foo-bar.host.com/entity/to/count

http://foo-bar.host.com/entity/to/
http://foo-bar.host.com/entity/to/count
http://foo-bar.host.com/entity/to/count

http://foo-bar.host.com/entity/to/find
http://foo-bar.host.com/entity/to/count
http://foo-bar.host.com/entity/to/count

http://foo-bar.host.com/entity/to/find/
http://foo-bar.host.com/entity/to/count/
http://foo-bar.host.com/entity/to/count/

http://foo-bar.host.com/entity/to/find?some=foo
http://foo-bar.host.com/entity/to/count?some=foo
http://foo-bar.host.com/entity/to/count?some=foo

http://foo-bar.host.com/entity/to/find/?foo=some
http://foo-bar.host.com/entity/to/count/?foo=some
http://foo-bar.host.com/entity/to/count/?foo=some

http://foo-bar.host.com/entity/to/count
http://foo-bar.host.com/entity/to/count
http://foo-bar.host.com/entity/to/count

http://foo-bar.host.com/entity/to/count/
http://foo-bar.host.com/entity/to/count/
http://foo-bar.host.com/entity/to/count/

http://foo-bar.host.com/entity/to/count?some=foo
http://foo-bar.host.com/entity/to/count?some=foo
http://foo-bar.host.com/entity/to/count?some=foo

http://foo-bar.host.com/entity/to/count/?foo=some
http://foo-bar.host.com/entity/to/count/?foo=some
http://foo-bar.host.com/entity/to/count/?foo=some

http://foo-bar.host.com/entity/toleaveMeAlone
http://foo-bar.host.com/entity/toleaveMeAlone
http://foo-bar.host.com/entity/toleaveMeAlone

http://foo-bar.host.com/entity/to/leaveMeAlone
http://foo-bar.host.com/entity/to/leaveMeAlone
http://foo-bar.host.com/entity/to/leaveMeAlone

http://foo-bar.host.com/entity/to/countleaveMeAlone
http://foo-bar.host.com/entity/to/countleaveMeAlone
http://foo-bar.host.com/entity/to/countleaveMeAlone

http://foo-bar.host.com/entity/to/count/leaveMeAlone
http://foo-bar.host.com/entity/to/count/leaveMeAlone
http://foo-bar.host.com/entity/to/count/leaveMeAlone

http://foo-bar.host.com/entity/to/countleaveMeAlone?some=foo
http://foo-bar.host.com/entity/to/countleaveMeAlone?some=foo
http://foo-bar.host.com/entity/to/countleaveMeAlone?some=foo

http://foo-bar.host.com/entity/to/count/leaveMeAlone?foo=some
http://foo-bar.host.com/entity/to/count/leaveMeAlone?foo=some
http://foo-bar.host.com/entity/to/count/leaveMeAlone?foo=some

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM