कैसे कई दोहराया समूहों पर कब्जा करने के लिए?


87

मुझे एक ही पैटर्न के कई समूहों को कैप्चर करने की आवश्यकता है। मान लीजिए, मेरे पास निम्नलिखित स्ट्रिंग है:

HELLO,THERE,WORLD

और मैंने निम्नलिखित पैटर्न लिखा है

^(?:([A-Z]+),?)+$

मैं जो करना चाहता हूं वह है, हर एक शब्द को कैप्चर करना, ताकि ग्रुप 1 है: "HELLO", ग्रुप 2 "THERE" है और ग्रुप 3 "वर्ल्ड" है "मेरा रेगेक्स वास्तव में केवल पिछले एक को कैप्चर कर रहा है, जो है" विश्व"।

मैं यहां अपनी नियमित अभिव्यक्ति का परीक्षण कर रहा हूं और मैं इसे स्विफ्ट के साथ उपयोग करना चाहता हूं (शायद स्विफ्ट में एक तरीका है कि किसी तरह मध्यवर्ती परिणाम प्राप्त कर सकें, ताकि मैं उनका उपयोग कर सकूं?)

अद्यतन: मैं उपयोग नहीं करना चाहता split। मुझे अब केवल उन सभी समूहों पर कब्जा करने की आवश्यकता है जो पैटर्न से मेल खाते हैं, न केवल पिछले एक।


5
पर विभाजित क्यों नहीं ,?
रॉक 321987

क्यों नहीं [A-Z]+या [^,]+परिणामों पर कब्जा करने के लिए
rock321987

rock321987, मैंने इनपुट स्ट्रिंग को अपडेट किया है। मुझे उपरोक्त पैटर्न का पालन करने वाली स्ट्रिंग को वास्तव में निकालने की आवश्यकता है। और मुझे केवल पिछले एक ही नहीं, सभी समूहों के पैटर्न से मेल खाना चाहिए। मैं जानना चाहता हूं कि इसे रेगेक्स के साथ कैसे करना है।
फबेलोव

2
rock321987, क्या अस्पष्ट है? मुझे एक मिलान समूह होने के लिए स्ट्रिंग के प्रत्येक शब्द की आवश्यकता है, लेकिन मेरा पैटर्न केवल पिछले एक को पकड़ता है ("वर्ल्ड")।
फबेलोव

1
सभी उत्तर ढूंढने के लिए इस उत्तर का उपयोग करें
rock321987

जवाबों:


65

पैटर्न में एक समूह के साथ, आप केवल उस समूह में एक सटीक परिणाम प्राप्त कर सकते हैं। यदि आपका कैप्चर समूह पैटर्न द्वारा दोहराया जाता है (आपने +आसपास के नॉन-कैप्चरिंग ग्रुप पर क्वांटिफायर का उपयोग किया है ), तो केवल अंतिम मान जो मैच करता है वह संग्रहीत होता है।

आपको पैटर्न के सभी मैचों को खोजने के लिए अपनी भाषा के रेगेक्स कार्यान्वयन कार्यों का उपयोग करना होगा, फिर आपको गैर-कैप्चरिंग समूह के एंकर और क्वांटिफायर को निकालना होगा (और आप गैर-कैप्चरिंग समूह को भी छोड़ सकते हैं)।

वैकल्पिक रूप से, अपने regex का विस्तार करें और पैटर्न को उस समूह के एक कैप्चरिंग समूह में शामिल करें जिसे आप परिणाम में प्राप्त करना चाहते हैं:

^([A-Z]+),([A-Z]+),([A-Z]+)$

17
स्ट्रिंग्स की एक अलग संख्या के लिए इसे कैसे समायोजित किया जाएगा? जैसे HELLO, World और HELLO, THERE, MY, WORLD। मैं दोनों उदाहरणों को संभालने के लिए सिर्फ एक अभिव्यक्ति की तलाश कर रहा हूं और लचीलेपन के साथ लंबे समय तक स्ट्रिंग सरणियों के लिए बनाया गया है
क्रिस

12
@ क्रिस यह सामान्यीकृत नहीं किया जा सकता है। जैसा कि उत्तर कहता है, एक कैप्चर समूह केवल एक चीज पर कब्जा कर सकता है, और कैप्चर समूहों की एक गतिशील संख्या बनाने का कोई तरीका नहीं है।
बारामार

7

मुझे लगता है कि आपको कुछ इस तरह की जरूरत है ...।

b="HELLO,THERE,WORLD"
re.findall('[\w]+',b)

जो पायथन 3 में वापस आएगा

['HELLO', 'THERE', 'WORLD']

re.findall('\w+',b)2 वर्ण छोटा है। एक चरित्र वर्ग के लिए कोई ज़रूरत नहीं के बाद से आप केवल एक अभिव्यक्ति है
जीन फ़्राँस्वा Fabre

3

उत्तर में पैराग्राफ 2 का अतिरिक्त उदाहरण प्रदान करने के लिए। मुझे यकीन नहीं है कि एक समूह का उपयोग करके तीन मैचों के बजाय एक मैच में तीन समूह प्राप्त करना आपके लिए कितना महत्वपूर्ण है। जैसे, ग्रूवी में:

def subject = "HELLO,THERE,WORLD"
def pat = "([A-Z]+)"
def m = (subject =~ pat)
m.eachWithIndex{ g,i ->
  println "Match #$i: ${g[1]}"
}

Match #0: HELLO
Match #1: THERE
Match #2: WORLD

3

बाइट कमांडर के जवाब को पढ़ने के बाद , मैं एक छोटे से संभावित सुधार की शुरुआत करना चाहता हूं:

आप एक रेगीक्स उत्पन्न कर सकते हैं जो या तो nशब्दों से मेल खाएगा , जब तक कि आपकेn पूर्वनिर्धारित नहीं होता है । उदाहरण के लिए, यदि मैं 1 और 3 शब्दों के बीच मेल खाना चाहता हूं, तो regexp:

^([A-Z]+)(?:,([A-Z]+))?(?:,([A-Z]+))?$

अगले वाक्यों का मिलान एक, दो या तीन कैप्चरिंग समूहों के साथ करेगा।

HELLO,LITTLE,WORLD
HELLO,WORLD
HELLO

आप इस नियमित अभिव्यक्ति के बारे में पूरी तरह से विस्तृत विवरण देख सकते हैं Regex101 पर

जैसा कि मैंने कहा, अपनी पसंदीदा भाषा का उपयोग करने वाले किसी भी समूह के लिए इस regexp को तैयार करना बहुत आसान है। चूंकि मैं बहुत तेज़ आदमी नहीं हूँ, यहाँ एक माणिक उदाहरण है:

def make_regexp(group_regexp, count: 3, delimiter: ",")
  regexp_str = "^(#{group_regexp})"
  (count - 1).times.each do
    regexp_str += "(?:#{delimiter}(#{group_regexp}))?"
  end
  regexp_str += "$"
  return regexp_str
end

puts make_regexp("[A-Z]+")

यह कहा जा रहा है, मैं सुझाव देता हूं कि उस स्थिति में नियमित अभिव्यक्ति का उपयोग नहीं करना चाहिए, splitआपकी आवश्यकताओं के आधार पर एक सरल से कुछ टोकन पैटर्न के कई अन्य महान उपकरण हैं। IMHO, एक नियमित अभिव्यक्ति उनमें से एक नहीं है। उदाहरण के लिए रूबी में मैं कुछ पसंद करता हूँ str.split(",")याstr.scan(/[A-Z]+/)


2

मुख्य अंतर दोहराए गए समूह को कैप्चर करने के बजाय कैप्चर किए गए समूह को दोहरा रहा है

जैसा कि आप पहले ही पता लगा चुके हैं, अंतर यह है कि पकड़े गए समूह को दोहराने से केवल अंतिम पुनरावृत्ति होती है। एक दोहराया समूह पर कब्जा करने से सभी पुनरावृत्तियों पर कब्जा हो जाता है।

PCRE (PHP) में:

((?:\w+)+),?
Match 1, Group 1.    0-5      HELLO
Match 2, Group 1.    6-11     THERE
Match 3, Group 1.    12-20    BRUTALLY
Match 4, Group 1.    21-26    CRUEL
Match 5, Group 1.    27-32    WORLD

चूंकि सभी कैप्चर ग्रुप 1 में हैं, इसलिए आपको केवल $1प्रतिस्थापन की आवश्यकता है।

मैंने इस सामान्य अभिव्यक्ति के निम्नलिखित सामान्य रूप का उपयोग किया:

((?:{{RE}})+)

Regex101 पर उदाहरण


1

आपके पास वास्तव में एक कब्जा समूह है जो कई बार मेल खाएगा। एकाधिक कैप्चर समूह नहीं।

जावास्क्रिप्ट (js) समाधान:

let string = "HI,THERE,TOM";
let myRegexp = /([A-Z]+),?/g;       //modify as you like
let match = myRegexp.exec(string);  //js function, output described below
while(match!=null){                 //loops through matches
    console.log(match[1]);          //do whatever you want with each match
    match = myRegexp.exec(bob);     //find next match
}

आउटपुट:

HI
THERE
TOM

वाक्य - विन्यास:

// matched text: match[0]
// match start: match.index
// capturing group n: match[n]

जैसा कि आप देख सकते हैं, यह किसी भी मैच के लिए काम करेगा।


0

मुझे पता है कि मेरा उत्तर देर से आया, लेकिन यह आज भी मेरे साथ है और मैंने इसे निम्नलिखित दृष्टिकोण से हल किया:

^(([A-Z]+),)+([A-Z]+)$

तो पहला समूह (([A-Z]+),)+अंतिम बार को छोड़कर सभी दोहराया पैटर्न ([A-Z]+)से मेल खाएगा जो अंतिम एक से मेल खाएगा। और यह गतिशील होगा चाहे स्ट्रिंग में कितने दोहराए गए समूह हों।


3
यह समस्या का समाधान नहीं है। प्रश्न स्ट्रिंग के मिलान के बारे में नहीं है, बल्कि सभी समूहों को कैप्चर करने के बारे में है। यह रेगेक्स अभी भी केवल पहले (दोहराए जाने वाले) समूह के साथ अंतिम समूह के लिए अंतिम मैच पर कब्जा करता है, साथ ही अंतिम समूह में मैच (अल्पविराम के बिना)।
gdwarf

0

क्षमा करें, स्विफ्ट नहीं, बस हाथ में निकटतम भाषा में अवधारणा का एक प्रमाण है।

// JavaScript POC. Output:
// Matches:  ["GOODBYE","CRUEL","WORLD","IM","LEAVING","U","TODAY"]

let str = `GOODBYE,CRUEL,WORLD,IM,LEAVING,U,TODAY`
let matches = [];

function recurse(str, matches) {
    let regex = /^((,?([A-Z]+))+)$/gm
    let m
    while ((m = regex.exec(str)) !== null) {
        matches.unshift(m[3])
        return str.replace(m[2], '')
    }
    return "bzzt!"
}

while ((str = recurse(str, matches)) != "bzzt!") ;
console.log("Matches: ", JSON.stringify(matches))

नोट: यदि आप वास्तव में इसका उपयोग करने जा रहे थे, तो आप मैच की स्थिति का उपयोग करेंगे जैसा कि रेगेक्स मैच फ़ंक्शन द्वारा दिया गया है, न कि एक स्ट्रिंग की जगह।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.