在正则表达式中添加括号会在ruby String#scan方法中将其分解

Max*_*ams 2 ruby regex

我有一个使用ruby 1.8.6和rails 2.2.2的应用程序(请不要谈论我需要如何更新).

我有一个服务器访问的文本doc,我正在从中抓取数据.线条就像

line1 = "93.97.151.194 - - [14/Nov/2013:20:13:30 +0000] \"GET /assets/dvd_files/pdfs/4139/DSB%20Guitar%20%E2%80%94%20medium.pdf HTTP/1.1\" 200 21172 \"http://www.mysite.co.uk/c/1267-ks3/131936-inspira-pops/134541-don-t-stop-believin-\" \"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36\""

line2 = "93.97.151.194 - - [14/Nov/2013:20:13:30 +0000] \"HEAD /assets/dvd_files/pdfs/4139/DSB%20Guitar%20%E2%80%94%20medium.pdf HTTP/1.1\" 200 21172 \"http://www.mysite.co.uk/c/1267-ks3/131936-inspira-pops/134541-don-t-stop-believin-\" \"Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36\""
Run Code Online (Sandbox Code Playgroud)

我用这个正则表达式收集了第一个路径部分:

#this works fine for the GET case
path = line1.scan(/\"GET\s[^\s]+/).first
=> "\"GET /assets/dvd_files/pdfs/4139/DSB%20Guitar%20%E2%80%94%20medium.pdf"
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但是有些行有HEAD作为方法,所以我修改了我的正则表达(GET|HEAD)而不仅仅是GET.现在,它只返回方法名称(GET或HEAD),没有路径.例如

path = line1.scan(/\"(GET|HEAD)\s[^\s]+/).first
=> ["GET"]
Run Code Online (Sandbox Code Playgroud)

现在我得到一个数组,而不是一个字符串:扫描的结果(没有先调用,是一个二维数组:

path = line1.scan(/\"(GET|HEAD)\s[^\s]+/)
=> [["GET"]]
Run Code Online (Sandbox Code Playgroud)

我不明白为什么这不起作用.这是扫描方法的特点吗?谁能让我直截了当?谢谢

编辑使用String #matre而不是#scan似乎工作:

path = line1.match(/\"(GET|HEAD)\s[^\s]+/).to_s
=> "\"GET /assets/dvd_files/pdfs/4139/DSB%20Guitar%20%E2%80%94%20medium.pdf"
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释为什么匹配工作和扫描不在这里?

Cri*_*scu 5

String#scan 将返回一个匹配数组,其中每个匹配项是一个数组,包含该匹配项的所有捕获组的值.

在Regex中,捕获组是括在括号中的表达式.

在您的情况下,因为您(GET|HEAD)在表达式中,这被认为是捕获并被返回.

为了说明这一点,让我们修改正则表达式/(GET|HEAD)\s([^\s]+)/(我也将该[^\s]+部分设为捕获组).对于您的line1变量,这将返回:

[["GET", "/assets/dvd_files/pdfs/4139/DSB%20Guitar%20%E2%80%94%20medium.pdf"]]
Run Code Online (Sandbox Code Playgroud)

(一个匹配两个捕获组).

固定

文件指出:

如果模式不包含组,则每个单独的结果由匹配的字符串$&组成.如果模式包含组,则每个单独的结果本身就是一个数组,每个组包含一个条目.

如果您希望GET|HEAD括在括号中,但不希望它被视为捕获组,请使用?:,如下所示:/(?:GET|HEAD)\s[^\s]+/.这将告诉Regex引擎括号只是包含表达式的一部分,但它不是捕获组.

在这里它是行动:http://ideone.com/0Ri1Uv