2011-04-16 54 views
1

我试图在一个小的ruby脚本中实现这个,并在http://www.rubular.com/上测试它,它在那里工作完美。不知道为什么它没有在实际的脚本中执行。这个RegEx有什么问题?

正则表达式: /(motion|links|sound|button|symbol)|(0.\d{8})|(\s\d{1}\s)|(\d{10} \ S)/

这是对文字:

试用ID:1 |试用类型:动作|招? 1 点击时间:0.87913100 1302969732

试用ID:7 |试用类型:按钮|招? 0 点击次数:0.19817800 1302987043

等等,等等

我试图抓住:只有号码,经过“试用型”的一个字。因此,对于示例的第一行,我只想要返回“1动作1 0.87913100 1302969732”。我还想在每次试验中的第一个号码之前保留空格。

我的短Ruby脚本

File.open('log.txt', 'r') do |file| 
    contents = file.readlines.to_s 
    regex = Regexp.new(/(motion|links|sound|button|symbol)|(0\.\d{8})|(\s\d{1}\s)|(\d{10}\s)/) 
    matchdata = regex.match(contents).to_a 
    matchdata.each do |match| 
    if match != nil 
     puts match 
    end 
    end 
end 

只输出两个 “1” 虽然。嗯...我知道它正在阅读文件内容,当我尝试了一个备用简单正则表达式时,它工作正常。

感谢您给我任何帮助! :)

回答

3

您需要转义正则表达式中的文字管道,填写其他缺少的文字(如Trick,\ ?, Click \ sTime:,删除一些空格等),并在适当的地方插入正则表达式空格...即

regex = Regexp.new(/(motion|links|sound|button|symbol)\s\|\sTrick\?\s*\d\s*Click\s+Time:\s+(0\.\d{,8})\s(\d{10}))/)

编辑:固定的括号嵌套在原

+0

噢,我并没有试图把所有的文字都写出来 - 我只是想在“试用类型”之后得到数字和单个单词。本来应该提到这个,对不起! – 2011-04-16 21:29:51

+0

@Jeff,这正是我的观点......审判后的单词类型和数字有更多的事情必须匹配。你不能假装他们不在那里......'ruby'当然不会。 – 2011-04-16 21:36:57

+0

哦,我当然无法理解正则表达式,然后 - 我不完全确定如何编辑表达式来说明这些,但不包括它们在结果中... – 2011-04-16 22:10:38

4

你想用String#scan

matchdata = contents.scan(regex) 

而且@Mike Penington是正确的,你不应该做if match != nil如果你这样做是正确的。你也必须清理你的正则表达式。正则表达式中的管道字符是一个特殊字符,用于表示匹配左侧或右侧,并且您具有必须转义的管道字符。

+0

这有助于吨,谢谢。为什么扫描会产生这样的差异?此外,这种方式我不断获得空阵列结果。我知道这可能是因为我在正则表达式上很糟糕,但是如果我能够消除空白数组斑点,它将完全解决我的问题......你知道我该怎么做吗? – 2011-04-16 22:16:02

2

如果您知道数据遵循特定的模式,你可以按照在正则表达式该模式,并拿起您需要的部分与()

/Trial ID: (\d+) \| Trial Type: (\w+) \| Trick\? (\d+) Click Time: ([\.\d]+) ([\.\d]+)/ 

您之前对数据了解得越多,您就可以更正确地使用正则表达式。 如果你看到的一些数据变化,和正则表达式匹配失败,那么就放松模式:

  • 如果开拓者ID,开拓者ID可以包括一个小数点,使用[\.\d]+代替\d+
  • 如果空间可以是一个以上,然后用[]+
  • 更换如果空间可以是一个选项卡,或者可以是不存在,使用或\s*[ \t]*
  • 如果Trial ID:部分可以表现为不同的短语,与.*?代替它,

等。

如果你不知道很多空格/制表符的显示,使用此:

/Trial\s*ID:\s*(\d+)\s*\|\s*Trial\s*Type:\s*(\w+)\s*\|\s*Trick\?\s*(\d+)\s*Click\s*Time:\s*([\.\d]+)\s+([\.\d]+)/ 
+0

甜,谢谢。那么,只有你括在括号里的东西实际上是由正则表达式拾取的吗?我没有意识到这个哈哈。我输入你放在这里的模式,这是有道理的,但没有结果,但......嗯...... – 2011-04-16 22:22:00

+0

然后,也许字符串有一些变化。例如,您可能有两个空格而不是一个,甚至没有空格,或者您可能有一个选项卡。你可能没有冒号等。你能弄清楚你的字符串有什么样的变化吗?你没有放在括号中的东西将作为'$ 0'的一部分出现,它代表匹配的整个部分。括号内的其他部分分别为'$ 1','$ 2',...。 – sawa 2011-04-16 22:23:58

+0

非常感谢你,在你和别人的帮助下,我解决了它。这是我的最后一个正则表达式:Regexp.new(/.*?Trial ID:(\ d +)。*?试用类型:(motion | links)。*?Trick \?(\ d +)。*?Click Time:(0 \。\ d {8})\ s(\ d {10})/) – 2011-04-16 22:31:18

1

这是那个时代,试图在一切大正则表达式让你的工作太辛苦的一个。简化的事情:

ary = [ 
    'Trial ID: 1 | Trial Type: motion | Trick? 1 Click Time: 0.87913100 1302969732', 
    'Trial ID: 7 | Trial Type: button | Trick? 0 Click Time: 0.19817800 1302987043' 
] 

ary.each do |li| 
    numbers = li.scan(/[\d.]+/) 
    trial_type = li[/Trial Type: (\w+)/, 1] 

    puts "%d %s %d %f %d\n" % [numbers.first, trial_type, *numbers[1 .. -1]] 
end 
# >> 1 motion 1 0.879131 1302969732 
# >> 7 button 0 0.198178 1302987043 

正则表达式模式是强大的,但人们认为它是一个男子汉,一切都在一条大线。你必须权衡这样做,首先必须将正则表达式放在一起,如果稍后解析文本中的某些内容发生变化,则需要维护它。