如何编写一个正则表达式来从这些URL中提取数字?

5

我正在尝试编写一个正则表达式来匹配这些URL中的数字(123456781234567890)。

http://www.example.com/p/12345678
http://www.example.com/p/12345678?foo=bar
http://www.example.com/p/some-text-123/1234567890?foo=bar

规则:

  • 数字始终跟在斜杠后面
  • 数字长度可以不同
  • 正则表达式必须检查URL中是否有/p/
  • 数字可能在URL结尾,也可能在变量后面

我的尝试:

\/p\/([0-9]+)

这符合第一和第二个,但不符合第三个。所以我尝试了:
\/p\/[^\/?]*\/?([0-9]+)

没有结果。 正则表达式101

2
你将在哪个正则表达式引擎中使用它(哪种编程语言)? - Michael Berkowski
"/[^\d]"?或者只是"[^\d]"或者"[^\d+]"应该也可以解决问题吧? - Adam
@MichaelBerkowski PHP - Nate
你的第一次尝试确实与第二个示例匹配(而不是第三个)。 - Michael Berkowski
@MichaelBerkowski 感谢您的提示 - 这就是我的粗心阅读的后果。 :) - rchang
5个回答

2

正则表达式可能不是这项工作的合适工具。从您的示例中可以看出,使用URL解析器拆分URL似乎更有意义。在每种情况下,数字部分似乎总是URL路径的最后一项。我不确定您使用的是哪种语言,但许多语言都提供函数来将URL解析为其组成部分。

$path = parse_url($url, PHP_URL_PATH);
if(strpos($path, "/p/") === 0) {
    $base = basename($path);
} else {
    // error
}

在假设你需要解析的字符串为$url的情况下,此方法总是有效的。


编辑以删除对 parse_url 的冗余调用。可以将 $path 传递给 basename 而不是再次调用 parse_url - superultranova

1
我扩展了您的版本,现在适用于所有示例:
\/p\/(.+\/)*(\d+)(\?.+=.+(&.+=.+)*)?$

如果您不在意URL是否有效,您可以将正则表达式缩小为:
\/p\/(.+\/)*(\d+)($|\?)

https://regex101.com/r/pW5qB3/2


这里末尾的所有内容都不是必要的,因为只有 /p/\d+ 是重要的。 - Michael Berkowski
1
@MichaelBerkowski但是OP提到数字应该是URL的最后一部分,只有参数可能跟随在后面,因此这确保了URL是有效的,并且只有参数在数字之后。 - msrd0
确实如此。您可以在其后跟随 ($|\?),以便查询字符串或字符串的结尾紧随其后。不必表达 key=value&key=value - Michael Berkowski
@DomStepek 这也将匹配 /sth/psth/sth/1234567890 - msrd0

0
\/p\/(?:.*\/)?(\d+)\b

你可以尝试这个。它将根据你的条件捕获整数。查看演示。获取捕获或组。

https://regex101.com/r/dU7oN5/29

$re = "/\\/p\\/(?:.*\\/)?(\\d+)\\b/";
$str = "http://www.example.com/p/12345678\nhttp://www.example.com/p/12345678?foo=bar\nhttp://www.example.com/p/some-text-123/1234567890?foo=bar";

preg_match_all($re, $str, $matches);

0

如果我理解正确,您想要的数字只能是:

  • 紧跟在URL的最后一个斜杠后面
  • 不能是变量的一部分,即/p/123?foo=bar456匹配123
    /p/foobar?foo=bar456不匹配任何内容

然后您可以使用以下正则表达式:

(?=/p/).*/\K\d+

解释

(?=/p/)  # lookahead: check '/p/' is in the URL
.*/      # go to the last '/' thanks to greediness
\K       # leave everything we have so far out of the final match
\d+      # select the digits just after the last '/'

为避免转义正斜杠,请勿将其用作正则表达式分隔符#(?=/p/).*/\K\d+#即可。
请参见此处的演示

-2
var regex = new Regex(@"/(?<ticket>\d+)");

var subject = "http://www.example.com/p/some-text-123/1234567890?foo=bar";

var ticket = regex.Match(subject).Groups["ticket"].Value;

输出:1234567890


2
这将匹配不包括“/p/”的URL,因为这是必需的。 - Michael Berkowski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接