2017-03-27 5 views
5

में अन्य नियमित अभिव्यक्ति में रेगुलर एक्सप्रेशन एम्बेड करने के लिए मैं एक स्ट्रिंग है:कैसे रूबी

'A Foo' 

और उस में "फू" खोजना चाहते हैं।

मैं रेगुलर एक्सप्रेशन है:

/foo/ 

है कि मैं एक और केस-संवेदी नियमित अभिव्यक्ति में embedding कर रहा हूँ, इसलिए मैं चरणों में पैटर्न का निर्माण कर सकते हैं:

foo_regex = /foo/ 
pattern = /A #{ foo_regex }/i 

लेकिन यह जीत लिया ' टी सही ढंग से मेल नहीं खाता:

'A Foo' =~ pattern # => nil 

यदि मैं टेक्स्ट को सीधे पैटर्न में एम्बेड करता हूं तो यह काम करता है:

'A Foo' =~ /A foo/i # => 0 

क्या गलत है?

+0

टिन मैन अच्छी सलाह देता है। रुबी एक पर्ल चाहता है। चूंकि यह प्रत्येक रेगेक्स को स्कोप्ड क्लस्टर समूह निर्माण (जैसे '(? Misx-misx: )' के साथ संकलित करता है। तो यह वाक्यविन्यास '/ string1 /' _no विकल्प_ के साथ एक regex संकलित करता है, और डिफ़ॉल्ट ''??misx: string 1)'' i' ध्वज के साथ संकलित एक और regex '/ string2/i 'है, इसे प्लस साइड में जोड़ता है '(? i-msx: स्ट्रिंग 2)'। चूंकि क्लस्टर समूह _scoped_ विकल्प हैं _inside_ क्लस्टर प्राथमिकता लेते हैं। तो, regex 2 के अंदर regex 1 है (? I-msx: string 2 (? -misx: string 1)) 'और निश्चित रूप से स्कोप' स्ट्रिंग 1' को निर्देशित करता है अब केस संवेदनशील है। – sln

+0

मैं नहीं कहूंगा रूबी एक पर्ल चाहता है। यह जावा, पर्ल और कुछ अन्य भाषाओं की तरह है जो उनके हिस्सों में मिश्रित है और रुबी के साथ आया है। –

+0

जैसे सॉर्ट करें .. कोई भी मास्टर – sln

उत्तर

5

सतह पर ऐसा लगता है कि किसी अन्य पैटर्न के अंदर एक पैटर्न एम्बेड करना बस काम करेगा, लेकिन यह रूबी में पैटर्न कैसे काम करता है, इसकी एक बुरी धारणा पर आधारित है, कि वे बस तार हैं। का उपयोग करना:

/foo/.class # => Regexp 

ऐसे में यह वैकल्पिक यह बनाने के लिए इस्तेमाल झंडे की जानकारी है:

(/foo/ ).options # => 0 
(/foo/i ).options # => 1 
(/foo/x ).options # => 2 
(/foo/ix ).options # => 3 
(/foo/m ).options # => 4 
(/foo/im ).options # => 5 
(/foo/mx ).options # => 6 
(/foo/imx).options # => 7 

या, यदि आप द्विआधारी की तरह:

foo_regex = /foo/ 

एक RegExp ऑब्जेक्ट बनाता है

'%04b' % (/foo/ ).options # => "0000" 
'%04b' % (/foo/i ).options # => "0001" 
'%04b' % (/foo/x ).options # => "0010" 
'%04b' % (/foo/xi ).options # => "0011" 
'%04b' % (/foo/m ).options # => "0100" 
'%04b' % (/foo/mi ).options # => "0101" 
'%04b' % (/foo/mx ).options # => "0110" 
'%04b' % (/foo/mxi).options # => "0111" 

और याद करता है जब भी Regexp का उपयोग किया जाता है, चाहे एक स्टैंडअलोन पैटर्न या किसी अन्य में एम्बेडेड हो।

आप कार्रवाई में देख सकते हैं अगर हम पैटर्न embedding के बाद कैसा दिखता है देखने के लिए लग रही है:

/#{ /foo/ }/ # => /(?-mix:foo)/ 
/#{ /foo/i }/ # => /(?i-mx:foo)/ 

?-mix: और ?i-mx: कैसे उन विकल्पों एक एम्बेडेड पैटर्न में प्रतिनिधित्व कर रहे हैं कर रहे हैं।

Options के लिए Regexp प्रलेखन के अनुसार

:

i, m, और x भी साथ उपसूचक स्तर पर लागू किया जा सकता (चालू-बंद?) निर्माण है, जो विकल्प पर सक्षम बनाता है , और कोष्ठक द्वारा संलग्न अभिव्यक्ति के लिए से विकल्प अक्षम करता है।

तो, Regexp उन विकल्पों को याद किया जाता है, यहां तक ​​कि बाहरी पैटर्न के अंदर, मैच विफल समग्र पैटर्न के कारण:

pattern = /A #{ foo_regex }/i # => /A (?-mix:foo)/i 
'A Foo' =~ pattern # => nil 

यह सुनिश्चित करें कि सभी उप-भाव अपने आसपास के प्रतिमानों से मिलान करने के लिए संभव है , फिर भी है कि जल्दी से भी जटिल या गंदा हो सकता है:

foo_regex = /foo/i 
pattern = /A #{ foo_regex }/i # => /A (?i-mx:foo)/i 
'A Foo' =~ pattern # => 0 

इसके बजाय हम source विधि है जो एक पैटर्न का पाठ देता है:

/#{ /foo/.source }/ # => /foo/ 
/#{ /foo/i.source }/ # => /foo/ 

एम्बेडेड पैटर्न भी विकल्प को याद के साथ समस्या यह प्रकट होता है जब इस तरह के union के रूप में अन्य Regexp तरीकों का उपयोग कर,:

/#{ Regexp.union(%w[a b]) }/ # => /(?-mix:a|b)/ 

और फिर, source मदद कर सकते हैं:

/#{ Regexp.union(%w[a b]).source }/ # => /a|b/ 

सब जानने के बाद कि:

foo_regex = /foo/ 
pattern = /#{ foo_regex.source }/i # => /foo/i 
'A Foo' =~ pattern # => 2 
+0

http://stackoverflow.com/a/42729953/128421, http://stackoverflow.com/a/16705515/128421, http://stackoverflow.com/a/23701327/128421 और http://stackoverflow.com इसके बारे में अतिरिक्त जानकारी के लिए/ए/38154742/128421। –

+0

अब मुझे पता है कि मैं किस लिंक से लिंक करूंगा;) –

1

"क्या गलत है?"

आपकी धारणा Regexp इंटरपोलेटेड है, यह गलत है।

#{...} के माध्यम से अंतर्वेशन अंतर्वेशित वस्तु पर to_s बुला द्वारा किया जाता है:

d = Date.new(2017, 9, 8) 
#=> #<Date: 2017-09-08 ((2458005j,0s,0n),+0s,2299161j)> 

d.to_s 
#=> "2017-09-08" 

"today is #{d}!" 
#=> "today is 2017-09-08!" 

और न सिर्फ स्ट्रिंग शाब्दिक के लिए, लेकिन यह भी नियमित अभिव्यक्ति शाब्दिक के लिए:

/today is #{d}!/ 
#=> /today is 2017-09-08!/ 

अपने उदाहरण में, ऑब्जेक्ट-टू-बी-इंटरपोलेटेड Regexp:

foo_regex = /foo/ 

और Regexp#to_s रिटर्न:

[...] नियमित अभिव्यक्ति और इसके विकल्प (चुनता है?: स्रोत) का उपयोग कर अंकन।

foo_regex.to_s 
#=> "(?-mix:foo)" 

इसलिए:

/A #{foo_regex}/i 
#=> /A (?-mix:foo)/i 

बस की तरह है:

"A #{foo_regex}" 
#=> "A (?-mix:foo)" 

दूसरे शब्दों में: क्योंकि जिस तरह से Regexp#to_s कार्यान्वित किया जाता है की, आप उनके झंडे खो बिना पैटर्न को जोड़ सकते हैं। यह एक सुविधा है, एक बग नहीं।

तो Regexp#to_s सिर्फ स्रोत (विकल्प) के बिना वापसी होगी, जिस तरह से आप उम्मीद करते हैं काम करेगा:

def foo_regex.to_s 
    source 
end 

/A #{foo_regex}/i 
#=> /A foo/i 

ऊपर कोड सिर्फ प्रदर्शन के उद्देश्य से है, ऐसा नहीं है।