रेगेक्स की सभी घटनाओं का मिलान कैसे करें


585

क्या रूबी में एक नियमित अभिव्यक्ति के हर मैच को खोजने का एक त्वरित तरीका है? मैंने रूबी एसटीएल में रेगेक्स ऑब्जेक्ट के माध्यम से देखा है और कोई फायदा नहीं हुआ।


3
मैंने यह पढ़ा है कि मैं सभी रेगेक्स पैटर्न के लिए एक स्ट्रिंग कैसे खोज सकता हूं और बुरी तरह से उलझन में था ...
ह्यूगोगा

जवाबों:


820

का उपयोग करना scanचाहिए चाल:

string.scan(/regex/)

9
लेकिन इस मामले में क्या लाजिमी है? "मुझसे मेल करो!" ], लेकिन /.../ की सभी घटनाएँ ["चटाई", "atc", "tch", "ch", ...]
माइकल डिकेन्स

13
ऐसा नहीं होगा। /.../ एक सामान्य लालची रीगेक्स है। यह मिलान की गई सामग्री पर वापस नहीं आएगा। आप एक आलसी regexp का उपयोग करने की कोशिश कर सकते हैं लेकिन यहां तक ​​कि शायद पर्याप्त नहीं होगा। अपने regexp को सही ढंग से व्यक्त करने के लिए regexp doc ruby-doc.org/core-1.9.3/Regexp.html पर एक नज़र डालें :
जीन

49
यह एक रूबी डब्ल्यूटीएफ की तरह लगता है ... अन्य रेगेक्स सामान के साथ रेगेक्सपी के बजाय स्ट्रिंग पर ऐसा क्यों है? डॉक्स पर भी कहीं भी इसका उल्लेख नहीं किया गया है
एंथ्रोपिक

8
मुझे लगता है कि यह इसलिए है क्योंकि इसे परिभाषित किया गया है और स्ट्रिंग ऑन रेगेक्स नहीं कहा जाता है ... लेकिन यह वास्तव में समझ में आता है। आप रेगेक्स # मैच का उपयोग करके सभी मैचों को पकड़ने के लिए एक नियमित अभिव्यक्ति लिख सकते हैं और कैप्चर किए गए समूहों पर पुनरावृति कर सकते हैं। यहां आप एक आंशिक मिलान फ़ंक्शन लिखते हैं और चाहते हैं कि यह दिए गए स्ट्रिंग पर म्यूटेंटर बार लागू हो, यह Regexp की जिम्मेदारी नहीं है। मेरा सुझाव है कि आप बेहतर समझ के लिए स्कैन के कार्यान्वयन की जाँच करें: रूबी-doc.org/core-1.9.3/String.html#method-i-scan
जीन

9
@ मिचेलडिकन्स: इस मामले में, आप उपयोग कर सकते हैं /(?=(...))/
कोनराड बोरोस्की

67

सभी मिलान स्ट्रिंग्स को खोजने के लिए, स्ट्रिंग की scanविधि का उपयोग करें।

str = "A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"
str.scan(/\d+/)
#=> ["54", "3", "1", "7", "3", "36", "0"]

यदि आप चाहते हैं, MatchDataजो Regexp matchविधि द्वारा लौटाए गए ऑब्जेक्ट का प्रकार है , तो उपयोग करें:

str.to_enum(:scan, /\d+/).map { Regexp.last_match }
#=> [#<MatchData "54">, #<MatchData "3">, #<MatchData "1">, #<MatchData "7">, #<MatchData "3">, #<MatchData "36">, #<MatchData "0">]

उपयोग करने MatchDataका लाभ यह है कि आप निम्न विधियों का उपयोग कर सकते हैं offset:

match_datas = str.to_enum(:scan, /\d+/).map { Regexp.last_match }
match_datas[0].offset(0)
#=> [2, 4]
match_datas[1].offset(0)
#=> [7, 8]

यदि आप अधिक जानना चाहते हैं तो इन प्रश्नों को देखें:

विशेष चरों के बारे में पढ़ना $&, $', $1, $2रूबी में सहायक भी हो जाएगा।


12

यदि आपके पास समूहों के साथ regexp है:

str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"
re=/(\d+)[m-t]/

आप scanमिलान समूहों को खोजने के लिए स्ट्रिंग की विधि का उपयोग कर सकते हैं :

str.scan re
#> [["54"], ["1"], ["3"]]

मिलान पैटर्न खोजने के लिए:

str.to_enum(:scan,re).map {$&}
#> ["54m", "1t", "3r"]

str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]की तुलना में अधिक मुहावरेदार हैstr.to_enum(:scan,re).map {$&}
टिन मैन

हो सकता है आपने गलत समझा हो। मेरे द्वारा उत्तर दिए गए उपयोगकर्ता के उदाहरण की नियमित अभिव्यक्ति थी: लिखने के लिए /(\d+)[m-t]/नहीं /\d+[m-t]/: re = /(\d+)[m-t]/; str.scan(re)एक ही है str.scan(/(\d+)[mt]/)लेकिन मुझे #> मिलता है [["" 54 "], [" 1 "], [" 3 "]]और "54m", "1t", "3r"]यह सवाल नहीं था: यदि मेरे पास एक समूह के साथ एक नियमित अभिव्यक्ति है और सभी पैटर्न को नियमित रूप से बदलने के बिना कब्जा करना चाहते हैं। अभिव्यक्ति (समूह को छोड़कर), मैं इसे कैसे कर सकता हूं? इस अर्थ में, एक संभावित समाधान, भले ही थोड़ा गूढ़ और पढ़ने में मुश्किल हो,:str.to_enum(:scan,re).map {$&}
एमवीपी

-1

आप उपयोग कर सकते हैं string.scan(your_regex).flatten। यदि आपके रेगेक्स में समूह हैं, तो यह एक सादे मैदान में वापस आएगा।

string = "A 54mpl3 string w1th 7 numbers scatter3r ar0und"
your_regex = /(\d+)[m-t]/
string.scan(your_regex).flatten
=> ["54", "1", "3"]

रेगेक्स एक नामित समूह भी हो सकता है।

string = 'group_photo.jpg'
regex = /\A(?<name>.*)\.(?<ext>.*)\z/
string.scan(regex).flatten

gsubयदि आप मैचडाटा चाहते हैं तो आप इसका उपयोग कर सकते हैं ।

str.gsub(/\d/).map{ Regexp.last_match }

से समूहीकरण निकालें your_regex = /(\d+)[m-t]/और आपको उपयोग करने की आवश्यकता नहीं होगी flatten। आपका अंतिम उदाहरण उपयोग करता है last_matchजो इस मामले में शायद सुरक्षित है, लेकिन एक वैश्विक है और संभवतः किसी भी regex को कॉल करने से पहले मिलान किए जाने पर अधिलेखित किया जा सकता है last_match। इसके बजाय शायद इसका उपयोग करना सुरक्षित है string.match(regex).captures # => ["group_photo", "jpg"]या string.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]जैसा कि अन्य उत्तरों में दिखाया गया है, पैटर्न और जरूरतों के आधार पर।
टिन मैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.