string = "This is a paragraph with a bunch3c:77:e6:68:66:e9of random MAC addresses 1100:50:7F:E6:96:20hello world 15:00s, 00:50:56:c0:00:08 some other text is written here 00-0C-29-38-1D-61 00:11:22book.FF:DD:CC"
mac_regex = /(?:[0-9A-F]{2}[\:\-]){5}[0-9A-F]{2}/i
mac_addresses = string.scan(mac_regex)
print mac_addresses
这将返回
["3c:77:e6:68:66:e9", "00:50:7F:E6:96:20", "00:50:56:c0:00:08", "00-0C-29-38-1D-61"]
。
如果我从
?:
中删除 mac_regex
,那么 mac_regex = /([0-9A-F]{2}[\:\-]){5}[0-9A-F]{2}/i
,那么 print mac_addresses
返回 [["66:"], ["96:"], ["00:"], ["1D-"]]
,这意味着 ([0-9A-F]{2}[\:\-]){5}
只匹配第五次出现的八位位组,而不是所有五个都匹配(我的理解是它应该将所有五个匹配在一起)。
为什么
([0-9A-F]{2}[\:\-]){5}
对应于匹配第五个八位位组,而不是一串5个八位位组?为什么需要 ?:
,([0-9A-F]{2}[\:\-]){5}
-> (?:[0-9A-F]{2}[\:\-]){5}
,使其对应于匹配 5 个八位字节的字符串?
(?:...)
是非捕获群。使用它是因为 String#scan 有两种不同的行为:
由于该模式只有一个组,并且它是非捕获的,因此
scan
使用第一个行为并仅以数组形式返回完整的匹配项。
删除
?:
意味着它切换到第二个行为并仅返回该一组。并且由于重复 {5}
是组的 outside,这意味着该组仅指每个八位位组,而不是所有五个八位位组;因此捕获的八位位组将是最后一个匹配的八位位组。
要在没有
?:
的情况下完成相同的行为,您需要为整个模式添加另一个捕获组,然后从结果中提取该组:
mac_regex = /(([0-9A-F]{2}[\:\-]){5}[0-9A-F]{2})/i
mac_addresses = string.scan(mac_regex).map(&:first)