2011-10-03 84 views
6

我想這將是一個愚蠢的錯誤,但對我來說,以下返回一個只包含「M」的數組。看到這個:Ruby正則表達式,只有一個捕獲(非常簡單!)

/(.)+?/.match("Many many characters!").captures 
=> ["M"] 

爲什麼不返回每個字符的數組?我一定錯過了明顯的東西,因爲我看不出這有什麼問題?

編輯:剛纔意識到,我不需要+?但如果沒有它,它仍然不起作用。

編輯:道歉!我將闡明:我的目標是允許用戶輸入正則表達式和樣式以及輸入文本文件,只要有匹配,文本將被一個html元素包圍,樣式將被應用,我不只是將字符串轉換成字符,我只使用給定的正則表達式,因爲它是最簡單的,儘管這是我的愚蠢。如何從scan()獲取捕獲組或者不可能?我看到$ 1包含「!」 (最後一場比賽?),而不是其他人。

編輯:天哪,這真的不是我的一天。正如injekt告訴我的那樣,捕獲被存儲在單獨的數組中。我如何從原始字符串中獲取這些捕獲的偏移量?我希望能夠獲得捕獲的偏移量,然後用另一個字符串包圍它。或者,這是什麼gsub? (我以爲只有更換了比賽,不是一個捕獲組)

希望最終編輯:權,讓我重新開始這個:P

所以,我有一個字符串。用戶將使用配置文件輸入正則表達式,然後使用與每個捕獲組關聯的樣式。我需要能夠掃描整個字符串並獲取每個組匹配的開始和結束或偏移量和大小。

因此,如果用戶已經配置了([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})(電子郵件地址),那麼我應該能夠得到:

[ ["elliotpotts", 0, 11], 
    ["sample.",  12, 7], 
    ["com",   19, 3] ] 

從字符串: 「[email protected]

如果不是很明顯,我只是有些問題:P。非常感謝你們,感謝你的耐心等待!

+0

我剛剛看到你的編輯,掃描的捕獲組存儲在單獨的數組中,只是嘗試你的正則表達式和在irb中的測試字符串,你會看到。答案仍然與您的編輯相同 –

+0

剛看到您的下一次編輯,您將不得不更新更多的信息。我現在有點困惑:P隨時拋出一個更完整的例子,無論它是如何做作,所以我們確切地知道你需要提取什麼 –

+0

好吧,用你最新的編輯更新我的答案。我現在有點時間了,所以這只是完整的解決方案,沒有解釋,讓我知道如果它沒有意義,我會更新它 –

回答

9

因爲您的捕獲只匹配一個單個字符。(.)+是不一樣的(.+)

>> /(.)+?/.match("Many many characters!").captures 
=> ["M"] 
>> /(.+)?/.match("Many many characters!").captures 
=> ["Many many characters!"] 
>> /(.+?)/.match("Many many characters!").captures 
=> ["M"] 

如果你想匹配的每一個字符遞歸使用String#scanString#split如果你不關心的捕捉組

使用掃描:

"Many many characters!".scan(/./) 
#=> ["M", "a", "n", "y", " ", "m", "a", "n", "y", " ", "c", "h", "a", "r", "a", "c", "t", "e", "r", "s", "!"] 

注其他的答案是使用(.),如果你關心捕獲組,那麼這很好,如果你不這樣做,這是沒有意義的,否則它會返回它的每一個字符N個獨立陣列,像這樣:

[["M"], ["a"], ["n"], ["y"], [" "], ["m"], ["a"], ["n"], ["y"], [" "], ["c"], ["h"], ["a"], ["r"], ["a"], ["c"], ["t"], ["e"], ["r"], ["s"], ["!"]] 

否則,只需使用split"Many many characters!".split(' ')"

編輯在回答您的編輯:

reg = /([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/ 
str = "[email protected]" 
str.scan(reg).flatten.map { |capture| [capture, str.index(capture), capture.size] } 
#=> [["elliotpotts", 0, 11], ["sample.", 12, 7], ["com", 19, 3]]` 

哦,你不需要掃描,你並不是真正掃描,所以你不需要遍歷,至少不是你提供的例子:

str.match(reg).captures.map { |capture| [capture, str.index(capture), capture.size] } 

還將努力

+0

謝謝!我還找到了一個替代答案,現在將它發佈。謝謝! – Ell

+0

給出的兩個代碼片段在一般情況下不適用於偏移量,它們只在匹配的子字符串全部不同時才起作用。例如,如果有3個匹配的「h」,那麼相同的索引('h'的第一個實例)全部返回3次。 str.index(capture)返回捕獲子字符串的FIRST實例的索引。 – jpwynn

0

它只返回一個字符,因爲這是你要求它匹配的。你可能想使用scan代替:

str = "Many many characters!" 
matches = str.scan(/(.)/) 
1

是,一些重要的東西被錯過;-)

(...)只介紹一個捕獲組:作爲指數是由正規只確定次小組賽的數量無關表達本身而不是輸入。

關鍵是一個「全局正則表達式」,它將按順序多次應用正則表達式。在Ruby中,這是從Regex#match反相到String#scan完成(很多其他語言有一個「/ G」正則表達式修改):

"Many many chara­cters!".sc­an(/(.)+?/­) 
# but more simply (or see answers using String#split) 
"Many many chara­cters!".sc­an(/(.)/­) 

快樂編碼

0

下面的代碼是從Get index of string scan results in ruby和修改我喜歡。

[].tap {|results| 
    "abab".scan(/a/) {|capture| 
     results.push(([capture, Regexp::last_match.offset(0)]).flatten) 
    } 
} 

=> [["a", 0], ["a", 2]] 
相關問題