2011-04-16 53 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 

正則表達式模式是強大的,但人們認爲它是一個男子漢,一切都在一條大線。你必須權衡這樣做,首先必須將正則表達式放在一起,如果稍後解析文本中的某些內容發生變化,則需要維護它。