2009-11-06 11 views
7

मैं स्केल में रेगेक्स के साथ एक बहु-पंक्ति वाली स्ट्रिंग के हिस्सों को कैप्चर करने की कोशिश कर रहा हूं। इनपुट फार्म का है:स्कैला रेगेक्स एकाधिक ब्लॉक कैप्चरिंग

val input = """some text 
       |begin { 
       | content to extract 
       | content to extract 
       |} 
       |some text 
       |begin { 
       | other content to extract 
       |} 
       |some text""".stripMargin 

मैं कई संभावनाएं है कि मुझे begin {} ब्लॉक के बाहर पाठ मिलना चाहिए की कोशिश की है। उनमें से एक:

val Block = """(?s).*begin \{(.*)\}""".r 

input match { 
    case Block(content) => println(content) 
    case _ => println("NO MATCH") 
} 

मैं एक NO MATCH मिलता है। अगर मैं \} ड्रॉप करता हूं तो रेगेक्स (?s).*begin \{(.*) जैसा दिखता है और यह अवांछित } और "कुछ टेक्स्ट" सहित अंतिम ब्लॉक से मेल खाता है। मैंने /.*begin \{(.*)\}/m के साथ rubular.com पर अपने regex की जांच की और यह कम से कम एक ब्लॉक से मेल खाता है। मैंने सोचा कि जब मेरा स्कैला रेगेक्स मेल खाता है तो मैं सभी ब्लॉक से मेल खाने के लिए findAllIn का उपयोग शुरू कर सकता हूं। मैं क्या गलत कर रहा हूं?

मैंने Scala Regex enable Multiline option पर एक नज़र डाली थी, लेकिन मैं टेक्स्ट ब्लॉक की सभी घटनाओं को कैप्चर करने में सक्षम नहीं था, उदाहरण के लिए, Seq[String]। किसी भी मदद की सराहना की है।

उत्तर

10

Alex के रूप में कहा है, जब पैटर्न मिलान का उपयोग कर नियमित अभिव्यक्ति से खेतों को निकालने के लिए, पैटर्न, जैसे कि वह घिरा था कार्य करता है (यानी, ^ और $ का उपयोग)। इस समस्या से बचने का सामान्य तरीका पहले findAllIn का उपयोग करना है। इस तरह:

val input = """some text 
       |begin { 
       | content to extract 
       | content to extract 
       |} 
       |some text 
       |begin { 
       | other content to extract 
       |} 
       |some text""".stripMargin 

val Block = """(?s)begin \{(.*)\}""".r 

Block findAllIn input foreach (_ match { 
    case Block(content) => println(content) 
    case _ => println("NO MATCH") 
}) 

अन्यथा, आप शुरुआत में .* का उपयोग करें और समाप्त कर सकते हैं कि प्रतिबंध के आसपास पाने के लिए:

:

val Block = """(?s).*begin \{(.*)\}.*""".r 

input match { 
    case Block(content) => println(content) 
    case _ => println("NO MATCH") 
} 

वैसे, आप शायद एक गैर उत्सुक मिलान चाहते

val Block = """(?s)begin \{(.*?)\}""".r 

Block findAllIn input foreach (_ match { 
    case Block(content) => println(content) 
    case _ => println("NO MATCH") 
}) 
+0

क्या आप जानते हैं कि यह कहीं भी दस्तावेज है? आपके विस्तृत उत्तर के लिए –

+1

धन्यवाद डैनियल। एक जादू की तरह काम करता है। –

+0

एलेक्स, इस बिंदु पर, मुझे यकीन नहीं है। मैंने रेगेक्स के साथ बहुत कुछ किया, यहां तक ​​कि लाइब्रेरी का विस्तार भी किया, कि मैं यह भी याद नहीं कर सकता कि पुस्तकालय क्या प्रदान करता है या नहीं! उदाहरण के लिए, मैं 'ब्लॉक findAllMatches इनपुट इनपुट (_ समूह 0) में लिखने जा रहा था, जब मुझे पता चला कि यह विधि लाइब्रेरी में मौजूद नहीं है। –

1

एक मैच करते समय, मेरा मानना ​​है कि एक पूर्ण मिलान की आवश्यकता है। आपका मैच के बराबर है:

val Block = """^(?s).*begin \{(.*)\}$""".r 

यह अंत करने के लिए काम करता है, तो आप जोड़ना *:।

val Block = """(?s).*begin \{(.*)\}.*""".r 

मैं इस पर किसी भी प्रलेखन ढूँढने में सक्षम नहीं किया गया है, लेकिन मैं यह एक ही सामना करना पड़ा मुद्दा।

+0

हाँ, काम किया है कि, धन्यवाद। –

0

अन्य उत्तरों के पूरक के रूप में, मैं kantan.regex के अस्तित्व को इंगित करना चाहता था, जो आपको निम्नलिखित लिखने देता है:

import kantan.regex.ops._ 

// The type parameter is the type as which to decode results, 
// the value parameters are the regular expression to apply and the group to 
// extract data from. 
input.evalRegex[String]("""(?s)begin \{(.*?)\}""", 1).toList 

यह पैदावार:

List(Success(
    content to extract 
    content to extract 
), Success(
    other content to extract 
)) 
संबंधित मुद्दे