正则表达式:提取URL字符串中倒数第二个斜杠之间的值

6

我有一个像这样的字符串:

http://www.example.com/value/1234/different-value

如何提取1234

注意:末尾可能带有斜杠:

http://www.example.com/value/1234/different-value
http://www.example.com/value/1234/different-value/

3
你使用的是哪种语言? - Tim Pietzcker
Ruby,我现在只是在测试你的答案,是否有更简单的方法可以基于最后一个标记来进行子字符串操作?哪种方法更有效率? - Daxon
4个回答

4
/([^/]+)(?=/[^/]+/?$)

应该是有效的。您可能需要根据您使用的语言进行不同的格式化。例如,在Ruby中,它是

if subject =~ /\/([^\/]+)(?=\/[^\/]+\/?\Z)/
    match = $~[1]
else
    match = ""
end

如果结尾没有 /,它就无法工作。编辑 - 如果将它们全部放在一起 :).. 它适用于单个情况。+1 - FailedDev
是的,Ruby使用斜杠来分隔正则表达式,并使用不同的字符串起始/结束锚点,这就是我提出问题的原因。我会进行编辑。 - Tim Pietzcker
我去掉了前导斜杠,这是对我有用的代码,谢谢 /([^/]+)(?=/[^/]+/?\Z)/ - Daxon
为什么要使用前瞻?完全可以将其移除 /([^/]+)/[^/]+/?$ - Qtax

2

使用Slice进行位置提取

如果您总是想从URI中提取第4个元素(包括方案),并且对您的数据有信心是规则的,那么您可以像下面这样使用Array#slice

'http://www.example.com/value/1234/different-value'.split('/').slice 4
#=> "1234"

'http://www.example.com/value/1234/different-value/'.split('/').slice 4
#=> "1234"

无论是否有尾斜杠、分割后的元素数量是否超过4个、第四个元素是否都是数字,这种方法都能可靠地工作。它之所以有效,是因为它基于路径中元素的位置,而不是元素本身的内容。但如果您尝试解析少于4个元素的URI,如http://www.example.com/1234/,则会得到nil

使用Scan/Match进行模式匹配

或者,如果您知道要查找的元素始终是唯一一个完全由数字组成的元素,可以使用String#match与环视来提取字符串的数字部分。
'http://www.example.com/value/1234/different-value'.match %r{(?<=/)\d+(?=/)}
#=> #<MatchData "1234">

$&
#=> "1234"

使用前后断言是为了将表达式锚定到路径上。如果没有它们,你会匹配到像w3.example.com这样的东西。如果目标元素的位置可能会改变,并且你可以保证你感兴趣的元素是唯一与锚定的正则表达式匹配的元素,那么这个解决方案是一个更好的方法。

如果有多个匹配项(例如http://www.example.com/1234/5678/),那么你可能想使用String#scan来选择第一个或最后一个匹配项。这是其中一些“了解你的数据”的事情;如果你的数据不规则,那么正则表达式并不总是最好的选择。


1

Javascript:

var myregexp = /:\/\/.*?\/.*?\/(\d+)/;
var match = myregexp.exec(subject);
if (match != null) {
    result = match[1];
}

适用于您的示例...但我确信它在一般情况下会失败...

Ruby编辑:

if subject =~ /:\/\/.*?\/.*?\/(.+?)\//
    match = $~[1]

确实有效。


我的输入是最高的Q值,你的正则表达式输出给我返回了://www.example.ie/value/12345。 - Daxon
抱歉,它们都没有工作,返回了相同的结果。 - Daxon

1
我认为这比已接受的答案更简单,因为它不使用任何肯定预查 (?=),而只是通过?字符使最后一个斜杠可选:
^.+\/(.+)\/.+\/?$

在Ruby中:
STDIN.read.split("\n").each do |nextline|
   if nextline =~ /^.+\/(.+)\/.+\/?$/
    printf("matched %s in %s\n", $~[1], nextline);
   else
    puts "no match"
   end
end

现场演示


让我们分解一下发生了什么:
  • ^: 行的开头
  • .+\/: 匹配斜杠之前的任何内容(贪婪匹配)
    • 由于我们稍后将匹配至少1个,最多2个斜杠,因此该斜杠将是倒数第二个斜杠(如http://www.example.com/value/1234/different-value)或倒数第三个斜杠(如http://www.example.com/value/1234/different-value/
    • 到目前为止,我们已经匹配了http://www.example.com/value/(由于贪婪性)
  • (.+)\/: 我们捕获的组1234由括号指示。它是紧随另一个斜杠后的任何内容。
    • 由于先前的匹配匹配了倒数第二个或第三个斜杠,因此这将匹配直到最后一个斜杠或倒数第二个斜杠
  • .+: 匹配任何内容。这将在我们的1234 / 之后,因此我们假设在1234 / 之后有字符(different-value
  • \/?: 可选地匹配另一个斜杠(different-value之后的斜杠)
  • $: 匹配行的结尾

请注意,在URL中,您可能不会有空格。我使用 . 字符是因为它很容易区分,但也许您可以使用 \S 来匹配非空格。
此外,您可能会使用 \A 代替 ^ 来匹配字符串的开头(而不是换行符后面),并使用 \Z 代替 $ 来匹配字符串的结尾(而不是在换行符处)。

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