我试图从字符串中获取id号码
id/number/2000GXZ2/ref=sr
Run Code Online (Sandbox Code Playgroud)
运用
(?:id\/number\/)([a-zA-Z0-9]{8})
Run Code Online (Sandbox Code Playgroud)
出于某种原因,非捕获组没有工作,给我:
id/number/2000GXZ2
Run Code Online (Sandbox Code Playgroud)
jac*_*umb 10
正如其他人所提到的,非捕获组仍然计入整体匹配.如果你不希望你的比赛中的那个部分使用lookbehind. Rubular例子
(?<=id\/number\/)([a-zA-Z0-9]{8})
Run Code Online (Sandbox Code Playgroud)
(?<= pat) - 正面的lookbehind断言:确保前面的字符匹配pat,但不包括匹配文本中的那些字符
此外,在这种情况下,不需要围绕id号的捕获组.
你有:
str = "id/number/2000GXZ2/ref=sr"
r = /
(?:id\/number\/) # match string in a non-capture group
([a-zA-Z0-9]{8}) # match character in character class 8 times, in capture group 1
/x # extended/free-spacing regex definition mode
Run Code Online (Sandbox Code Playgroud)
然后(使用String#[]):
str[r]
#=> "id/number/2000GXZ2"
Run Code Online (Sandbox Code Playgroud)
返回整个匹配,正如它应该的那样,而不仅仅是捕获组 1 的内容。有几种方法可以解决这个问题。首先考虑不使用捕获组的那些。
@jacob.m 建议将第一部分放在积极的回顾中(从他的代码中稍作修改):
r = /
(?<=id\/number\/) # match string in positive lookbehind
[[:alnum:]]{8} # match >= 1 alphameric characters
/x
str[r]
#=> "2000GXZ2"
Run Code Online (Sandbox Code Playgroud)
另一种选择是:
r = /
id\/number\/ # match string
\K # forget everything matched so far
[[:alnum:]]{8} # match 8 alphanumeric characters
/x
str[r]
#=> "2000GXZ2"
Run Code Online (Sandbox Code Playgroud)
\K 当要忘记的匹配是可变长度时特别有用,因为(在 Ruby 中)积极的lookbehinds 不适用于可变长度匹配。
对于这两种方法,如果要匹配的部分仅包含数字和大写字母,您可能需要使用[A-Z0-9]+代替[[:alnum:]](尽管后者包括 Unicode 字母,而不仅仅是来自英文字母的字母)。事实上,如果所有条目都具有您的示例的形式,您可能可以使用:
r = /
\d # match a digit
[A-Z0-9]{7} # match >= 0 capital letters or digits
/x
str[r]
#=> "2000GXZ2"
Run Code Online (Sandbox Code Playgroud)
另一种方法是保留您的捕获组。一种简单的方法是:
r = /
id\/number\/ # match string
([[:alnum:]]{8}) # match >= 1 alphameric characters in capture group 1
/x
str =~ r
str[r, 1] #=> "2000GXZ2"
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用String#sub将整个字符串替换为捕获组的内容:
r = /
id\/number\/ # match string
([[:alnum:]]{8}) # match >= 1 alphameric characters in capture group 1
.* # match the remainder of the string
/x
str.sub(r, '\1') #=> "2000GXZ2"
str.sub(r, "\\1") #=> "2000GXZ2"
str.sub(r) { $1 } #=> "2000GXZ2"
Run Code Online (Sandbox Code Playgroud)