2012-03-02 11 views
10

मूल रूप से प्रश्न शीर्षक में कहा गया है, क्या रूबी तारों पर एक विधि है जो String#Scan के समतुल्य है लेकिन प्रत्येक मैच की केवल एक सूची लौटने की बजाय, यह MatchData की एक सरणी वापस कर देगी रों? उदाहरण के लिए:रूबी स्ट्रिंग # वापसी के बराबर स्कैन मैचडाटा

# Matches a set of characters between underscore pairs 
"foo _bar_ _baz_ hashbang".some_method(/_[^_]+_/) #=> [#&ltMatchData "_bar_"&rt, &ltMatchData "_baz_"&rt] 

या किसी भी तरह से मैं वही या समान परिणाम प्राप्त कर सकता हूं। मैं रूबी तारों के भीतर "स्ट्रिंग्स" की स्थिति और विस्तारों को ढूंढने के लिए ऐसा करना चाहता हूं, उदा। "goodbye और "world" "अलविदा" क्रूर 'दुनिया' के अंदर "।

उत्तर

7

आप MatchData#end और के pos पैरामीटर का शोषण करके आसानी से अपना स्वयं का निर्माण कर सकते हैं। कुछ इस तरह:

def matches(s, re) 
    start_at = 0 
    matches = [ ] 
    while(m = s.match(re, start_at)) 
     matches.push(m) 
     start_at = m.end(0) 
    end 
    matches 
end 

और फिर:

>> matches("foo _bar_ _baz_ hashbang", /_[^_]+_/) 
=> [#<MatchData "_bar_">, #<MatchData "_baz_">] 
>> matches("_a_b_c_", /_[^_]+_/) 
=> [#<MatchData "_a_">, #<MatchData "_c_">] 
>> matches("_a_b_c_", /_([^_]+)_/) 
=> [#<MatchData "_a_" 1:"a">, #<MatchData "_c_" 1:"c">] 
>> matches("pancakes", /_[^_]+_/) 
=> [] 

आप कर सकते थे बंदर पैच कि स्ट्रिंग में यदि आप वास्तव में चाहते थे।

+0

बहुत बढ़िया, यह वही है जो मुझे इसकी आवश्यकता है! हां, मैं सोच रहा था कि मैं इस तरह कुछ कैसे कर सकता था, लेकिन मुझे pos परम के बारे में पता नहीं था :) – Jwosty

11
memo = [] 
"foo _bar_ _baz_ hashbang".scan(/_[^_]+_/) { memo << Regexp.last_match } 
=> "foo _bar_ _baz_ hashbang" 
memo 
=> [#<MatchData "_bar_">, #<MatchData "_baz_">] 
+3

+1 बहुत संक्षिप्त। और 'Regexp.last_match' थ्रेड-लोकल है, इसलिए आप दौड़ की स्थिति में नहीं भागेंगे। – Kelvin

1

आप MatchData प्राप्त करने की आवश्यकता नहीं है, तो वापस है, यहाँ StringScanner का उपयोग कर एक तरीका है।

require 'strscan' 

rxp = /_[^_]+_/ 
scanner = StringScanner.new "foo _barrrr_ _baz_ hashbang" 
match_infos = [] 
until scanner.eos? 
    scanner.scan_until rxp 
    if scanner.matched? 
    match_infos << { 
     pos: scanner.pre_match.size, 
     length: scanner.matched_size, 
     match: scanner.matched 
    } 
    else 
    break 
    end 
end 

p match_infos 
# [{:pos=>4, :length=>8, :match=>"_barrrr_"}, {:pos=>13, :length=>5, :match=>"_baz_"}] 
संबंधित मुद्दे