【问题标题】:PHP regex replace a word in url pathPHP正则表达式替换url路径中的单词
【发布时间】:2017-06-12 10:31:04
【问题描述】:

我正在尝试替换 url 路径中的一个单词。

F.e. host.com/path/to/find 应该变成 host.com/path/to/count

但我显然没有让这个工作。

我试图得到这个组:(?:/count|/find)? 在字符串的末尾

所有在它前面的都用$1/count替换它。

但总是当我尝试在 (?:/count|/find)? 之前获取部分时,我把它搞砸了。

这是一个测试:

编辑:所有键都代表测试(源)url。所有的值都代表预期的结果。

因此,如果路径上没有“/count”,则应该添加它。

如果末尾有“/count”,则无事可做。

如果路径末尾有“/find”,则应更改为“/count”。

如果 url 中有工作的“count”somewhere(如“countleaveMeAlone”),则不应更改(ofc)。

$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));
}

非常感谢任何帮助

【问题讨论】:

  • 所以你想在 URL 中用 'count' 替换 'find' 吗?在我回答之前想澄清一下。
  • “find”可以在 url 中出现多次还是在路径中出现一次?
  • $url = preg_replace("#\A(.*)(?:/count|/find)?\z#", '$1/count', $url);将其替换为 $url = preg_replace( "#\A(.*)(?:/count|/find)?\z#", "$1/count", $url );
  • 为什么不使用 str_replace?如果这只是我们正在谈论的静态替换
  • 你说得对@Andreas,str_replace也可以用,如果你需要preg_split$url = preg_replace('/\/find/', '/count');

标签: php regex url


【解决方案1】:
$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 />";
}

【讨论】:

  • 不起作用。 F.e.第一个http://foo-bar.host.com/entity/to 不会更改为http://foo-bar.host.com/entity/to/count
  • 只是我替换 find 来计数。请说明您的要求。
【解决方案2】:

模式:(Pattern/Replacement Demo with Official Explanation)

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

外行的崩溃:

  • ~ 起始模式分隔符(不是斜线,所以斜线不需要在模式中转义)
  • ^匹配字符串的开头
  • ([^?]+?) 捕获一个或多个不是问号的字符(惰性/非贪婪)
  • /? 匹配零个或一个斜线
  • (捕获...
    • (?:(?:/count|leaveMeAlone)(*SKIP)(*FAIL)) 如果在 ? 之前找到 /countleaveMeAlone,则取消整个字符串的资格
    • |或者
    • (?:find/??)? 可选择使用 0 个或一个尾随斜杠捕获 find(惰性)
  • ) ...结束捕获
  • ((?:(?&lt;=find)/)?) 如果前面有 find,则捕获零或一个斜线
  • ((?:\?.*)?)捕获url的可选查询字符串部分
  • $匹配字符串的结尾
  • ~ 结束模式分隔符

代码:(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
}

输出:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-10
    • 2022-12-10
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 2020-01-06
    • 1970-01-01
    相关资源
    最近更新 更多