【问题标题】:Replace page number in url (php)替换 url 中的页码 (php)
【发布时间】:2014-03-17 20:07:52
【问题描述】:
我已经为此工作了几个小时,但我找不到一种方法来替换 url 中的页码而不破坏它。
我有这种网址:
http://example.com/s/192090/1/text
其中“192090”是帖子id,1是页码,“text”是帖子标题。
我想要的是替换页码,保留url的其余部分:
http://example.com/s/192090/2/text
http://example.com/s/192090/3/text
http://example.com/s/192090/12/text
http://example.com/s/192090/542/text
等等。
问题是,我无法正确使用正则表达式。
如果我尝试:
preg_replace("/[0-9]+/[0-9]+/",'$0/2',$url);
我明白了:
http://example.com/s/192090/1/2/text
我尝试了很多正则表达式组合,但我对正则表达式没有任何经验。
问题在于 /s/NUM_POST/NUM_PAGE 的长度都是可变的。我需要保留第一个,并替换第二个而不弄乱 NUM_POST 或最后的博客标题。
有什么想法吗?
【问题讨论】:
标签:
php
regex
url
preg-replace
【解决方案1】:
这行得通,不必处理反向引用,这让我很头疼:
$url = '/s/192090/1/2/text';
$page_number = 55;
$pattern = '/\/(s)\/(\d+)\/(\d+)\/(.*)/';
$replacement = '/$1/$2/'.$page_number.'/$4';
echo preg_replace($pattern, $replacement, $url);
但是,它假设您有前导 /s/,可以将其更改为:
'/\/(.*)\/(\d+)\/(\d+)\/(.*)/'
【解决方案2】:
使用分组(使用(..))和对该组的反向引用:
$newUrl = preg_replace('#s/([0-9]+)/[0-9]+#', 's/\1/' . $newPageNr, $url);
\1 表示第一组。
【解决方案3】:
你为什么不尝试使用explode()?
$example = "http: //example.com/s/192090/1/text";
$info = explode("/", $example);
$pid = $info[4];
$page = $info[5];
$text = $info[6];
【解决方案4】:
这是另一种方法,通过爆炸和内爆:
$url = "http://example.com/s/192090/1/text";
$parsed = parse_url($url); //generate associative array
$exploded = explode("/", $parsed['path']); //explodes path
//replaces the crucial number
$exploded[3] = 7;
$parsed['path'] = implode("/", $exploded);//recreates the path
//concatenates the URL - may also be able to use http_build_url here
$newURL = $parsed['scheme'] ."://" . $parsed['host'] . $parsed['path'];
echo $newURL;
【解决方案5】:
这是我所做的替换:
$new_digit = 1978;
$url = 'http://example.com/s/192090/1/text';
print "Original URL: ".$url;
$url = preg_replace('~s/\d+/\K\d+(?=/)~', $new_digit, $url);
print "\n New URL: ".$url;
这个输出:
Original URL: http://example.com/s/192090/1/text
New URL: http://example.com/s/192090/1978/text
这里是正则表达式的解释:
s/ \d+/ \K \d+ (?=/)
^ ^ ^ ^ ^
1 2 3 4 5
-
s/ 这是一个锚点,并不是真正必要的。您可以从第二个项目开始表达式,但仍然得到相同的结果。我把它放在那里是因为我想展示某种锚。
-
\d+/ 在这里,我们正在寻找一个或多个数字,后跟一个正斜杠。
-
\K 这告诉正则表达式从这里重新开始。现在我们已经成功匹配到了这一点,我们想在这之后拔出所有东西。 (我们进行了匹配,但我们不想捕获它,我们只是记下它的位置,以便我们知道从哪里开始替换。
-
\d+ 一位或多位数字。这是表达式中唯一将被实际捕获的部分。因此,这是表达式中唯一将被替换的部分。
-
(?=/) 这是在捕获的数字后查找斜线的前瞻。未捕获前瞻,所有这一切实际上都是为\d+ 设置结尾。由于斜线不是数字,它不会被\d+ 匹配,这里也没有必要。我只是用它来显示一个锚。没有它,表达式也能正常工作。
如果没有不必要的锚点(第 1 项和第 5 项),您可以根据需要将表达式修剪为以下内容:
~\d+/\K\d+~
并且仍然得到相同的结果。
Here is a working demo