RegExp के निष्पादन () फ़ंक्शन और स्ट्रिंग के मिलान () फ़ंक्शन के बीच अंतर क्या है?


122

अगर मैं इसे चलाता हूं:

/([^\/]+)+/g.exec('/a/b/c/d');

मैंने इसे प्राप्त किया:

["a", "a"]

लेकिन अगर मैं इसे चलाता हूं:

'/a/b/c/d'.match(/([^\/]+)+/g);

तब मुझे इसका अपेक्षित परिणाम मिलता है:

["a", "b", "c", "d"]

क्या फर्क पड़ता है?


4
आप execसभी उप-चयन प्राप्त करने के लिए लूप करते हैं ।
zzzzBov

2
ध्यान दें कि दूसरे +की जरूरत नहीं है क्योंकि matchसभी उप-अभिव्यक्तियों को पहले से ही वापस कर दिया जाएगा। .execकेवल हर बार एक रिटर्न देता है, इसलिए इसकी जरूरत नहीं है +
pimvdb

3
शीर्ष पर, दो प्लसस जैसे नेस्टेड मात्रा का उपयोग बेहद सावधानी से किया जाना चाहिए क्योंकि वे आसानी से भयावह बैकट्रैकिंग का नेतृत्व करते हैं
मैरियस शुल्ज

1
@MariusSchulz लिंक के लिए धन्यवाद। यह मेरे पास रहने वाले क्वांटिफायर और परमाणु समूहन के बारे में जानने के लिए आगे बढ़ता है। बहुत अच्छी बातें समझने के लिए।
जस्टिन वारकेंटिन

जवाबों:


118

execएक वैश्विक नियमित अभिव्यक्ति के साथ एक लूप में उपयोग करने के लिए है, क्योंकि यह अभी भी सभी मिलान किए गए उप-संदर्भों को पुनर्प्राप्त करेगा। इसलिए:

var re = /[^\/]+/g;
var match;

while (match = re.exec('/a/b/c/d')) {
    // match is now the next match, in array form.
}

// No more matches.

String.match आपके लिए ऐसा करता है और पकड़े गए समूहों को त्याग देता है।


39
मेरे पास इस उत्तर को जोड़ने के लिए कुछ है, किसी को नियमित अभिव्यक्ति शाब्दिक स्थिति के भीतर नहीं रखना चाहिए, इस तरह while(match = /[^\/]+/g.exec('/a/b/c/d')या यह एक अनन्त लूप बनाएगा !!! जैसा कि MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
yeyo

7
@yeyo: विशेष रूप से, यह एक ही नियमित अभिव्यक्ति ऑब्जेक्ट होना चाहिए। एक शाब्दिक कि पूरा नहीं करता है।
Ry-

@ Ry- मुझे लगता है कि एक को ध्यान देना चाहिए कि यह व्यवहार ES5 में पेश किया गया था। ES5 से पहले new RegExp("pattern")और /pattern/विभिन्न चीजों का मतलब है।
रॉबर्ट

75

एक तस्वीर बेहतर है, आप जानते हैं ...

re_once = /([a-z])([A-Z])/
re_glob = /([a-z])([A-Z])/g

st = "aAbBcC"

console.log("match once="+ st.match(re_once)+ "  match glob="+ st.match(re_glob))
console.log("exec once="+ re_once.exec(st) + "   exec glob="+ re_glob.exec(st))
console.log("exec once="+ re_once.exec(st) + "   exec glob="+ re_glob.exec(st))
console.log("exec once="+ re_once.exec(st) + "   exec glob="+ re_glob.exec(st))

फर्क देखें?

नोट: हाइलाइट करने के लिए, ध्यान दें कि कैप्चर किए गए समूह (जैसे: a, A) मिलान किए गए पैटर्न (जैसे: AA) के बाद वापस आ गए हैं, यह केवल मिलान किए गए पैटर्न नहीं है।



23

यदि आपका रेगेक्स वैश्विक है, और आप कब्जा कर रहे हैं, तो आपको निष्पादन का उपयोग करना होगा। मैच आपके सभी कैप्चर को वापस नहीं करेगा।

जब मिलान हो रहा हो (कैप्चरिंग नहीं हो) तो मैच बहुत अच्छा काम करता है। आप इसे एक बार चलाते हैं और यह सभी मैचों की एक सरणी देता है। (हालांकि अगर रेगेक्स वैश्विक नहीं है, तो मैच मैच दिखाएगा और उसके बाद कब्जा कर लेगा)

जब आप कैप्चर कर रहे होते हैं, तब Exec का उपयोग करते हैं, और हर बार इसे निष्पादित करने पर यह मैच देता है, इसके बाद कैप्चर करता है। (मैच पूर्ण मैच देने के बाद कैप्टेंसी का व्यवहार करेगा, केवल तभी जब रेक्सक्स वैश्विक नहीं होगा)।

Exec के साथ एक और उपयोग, एक मैच का सूचकांक या स्थिति प्राप्त कर रहा है। जब आपके पास अपने रेगेक्स के लिए एक चर होता है, तो आप .lastIndex का उपयोग कर सकते हैं और मिलान की स्थिति प्राप्त कर सकते हैं। एक रेगेक्स ऑब्जेक्ट में .lastIndex, और रेगेक्स ऑब्जेक्ट है जो आप करते हैं। डॉट मैच एक स्ट्रिंग पर किया जाता है और आप तब regex ऑब्जेक्ट डॉट lastIndex नहीं कर पाएंगे

एक स्ट्रिंग में, मैच फंक्शन होता है, जिसे एक रेगेक्स पास किया जाता है। और एक रेगेक्स, में निष्पादन फ़ंक्शन होता है, और एक स्ट्रिंग पारित किया जाता है

आप कई बार चलाते हैं। मैच आप एक बार चलाएं

मैच का उपयोग करना अच्छा है जब कैप्चरिंग नहीं है और जब आप कैप्चर कर रहे हैं तो निष्पादन का उपयोग कर सकते हैं जो अधिक शक्तिशाली है क्योंकि यह कैप्चर करने के लिए अच्छा है, लेकिन यदि आप कैप्चर करते समय मैच का उपयोग करते हैं, तो देखें कि यह कैप्चर दिखाता है जब रेगेक्स वैश्विक नहीं है, लेकिन doesn जब regex वैश्विक है, तो शो कैप्चर नहीं होता है।

> "azb".match(/a(z)b/);
[ "azb", "z" ]

> "azb".match(/a(z)b/g);
[ "azb" ]
>

एक और बात यह है कि यदि आप निष्पादन का उपयोग करते हैं, तो ध्यान दें कि रेगेक्स पर कॉल किया जाता है, तो यदि आपने रेगेक्स के लिए एक चर का उपयोग किया है, तो आप अधिक शक्ति प्राप्त करेंगे

जब आप रेगेक्स के लिए वैरिएबल का उपयोग नहीं करते हैं, तो आपको मैच नहीं मिलते हैं, इसलिए रेग्ज के लिए वैरिएबल का उपयोग करें, जब निष्पादन का उपयोग करें

> /./g.exec("abc")
[ "a" ]
> /./g.exec("abc")
[ "a" ]
> /./g.exec("abc")
[ "a" ]
>
> /[a-c]/g.exec("abc")
[ "a" ]
> /[a-c]/g.exec("abc")
[ "a" ]
>

> var r=/[a-c]/g
> r.exec("abc")
[ "a" ]
> r.exec("abc")
[ "b" ]
> r.exec("abc")
[ "c" ]
> r.exec("abc")
null
>

और निष्पादन के साथ, आप मैच का "इंडेक्स" प्राप्त कर सकते हैं

> var r=/T/g
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
2
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
6
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
9
> r.exec("qTqqqTqqTq");
null
> r.lastIndex
0
>

इसलिए यदि आप इंडेक्स या कैप्चरिंग चाहते हैं, तो निष्पादन का उपयोग करें (ध्यान रखें कि जैसा कि आप देख सकते हैं, "इंडेक्स" के साथ, "इंडेक्स" जो इसे देता है वह वास्तव में एक nth घटना है, यह 1 से गिना जा रहा है। इसलिए आप उचित प्राप्त कर सकते हैं) सूचकांक घटाकर 1. और जैसा कि आप देख सकते हैं यह 0 देता है - 0 के अंतिम बिंदु - नहीं मिला है)।

और यदि आप मैच को फैलाना चाहते हैं, तो जब आप कैप्चर कर रहे हों, तब इसका उपयोग कर सकते हैं, लेकिन रेगेक्स के ग्लोबल होने पर, और जब आप इसके लिए करते हैं, तब ऐरे की सामग्री सभी मैच नहीं होती हैं, लेकिन पूर्ण होती हैं कैप्चर के बाद मैच।


हां, के कामकाज r.lastIndexको समझना महत्वपूर्ण कारक है execऔर इसके बीच अंतर को समझना है match
19

@barlop "मैच सभी कैप्चर से मेल नहीं खाएगा", गंभीरता से? "a, b, c, aa, bb, cc" .match (/ (\ w +) / g) => ["a", "b", "c", "aa", "bb", "cc" ]। कैसे समझाया जाए कि यह उन सभी को खत्म कर दिया?
मि।

@barlop If your regex is global, and you are capturing, then you must use exec. Match won't return all your captures.मुझे कंसोल पर मिला। "a,b,c,aa,bb,cc".match(/(\w+)/g);ओपेरा, फ़ायरफ़ॉक्स को कॉपी / पेस्ट करें ।
मि। विदेह

@ मेरा वीडियो आप अपनी गलत बोली में आपके द्वारा की गई भाषा का उपयोग नहीं करेंगे। और क्या मायने रखता है, जो दिखाया गया है और जो हम देख पा रहे हैं .. क्या पर्दे के पीछे कोई कैशिंग भी प्रासंगिक नहीं है। और जब से मैंने इस पर ध्यान दिया है, तब से कुछ समय हो गया है, लेकिन यह सभी कैप्चर नहीं दिखाती है .. भले ही आप अपना उदाहरण दें "a,b,c,aa,bb,cc".match(/(\w+)/g) कि यह क्या हो रहा है, यह सभी मैचों को दिखाता है, और यह सिर्फ इतना होता है कि आपने हर मैच पर कब्जा कर लिया, यदि यह सभी कैप्चर दिखाते हैं, तो यह बिल्कुल समान (cntd) दिखाई देगा
बार्लॉप

(cntd) तो शायद आप सोच रहे हैं कि यह कैप्चर दिखा रहा है, लेकिन ऐसा नहीं है, यह मैच दिखा रहा है
barlop

6

.Match () समारोह str.match(regexp)निम्न करेगा:

  • अगर वहाँ है एक मैच में वापस कर देंगे:
    • अगर gझंडा है regexp में इस्तेमाल किया: यह सब सबस्ट्रिंग वापस आ जाएगी (कैप्चर समूहों अनदेखी)
    • यदि gझंडा regexp में उपयोग नहीं किया जाता है: यह उसी तरह वापस आ जाएगाregexp.exec(str)
  • अगर कोई मैच नहीं है तो वह वापस आ जाएगी:
    • null

झंडे का उपयोग .match () के उदाहरण g:

var str = "qqqABApppabacccaba";
var e1, e2, e3, e4, e5;
e1 = str.match(/nop/g); //null
e2 = str.match(/no(p)/g); //null
e3 = str.match(/aba/g); //["aba", "aba"]
e4 = str.match(/aba/gi); //["ABA", "aba", "aba"]
e5 = str.match(/(ab)a/g); //["aba", "aba"] ignoring capture groups as it is using the g flag

और .match () के बिना gध्वज के बराबर है .exec () :

e1=JSON.stringify(str.match(/nop/))===JSON.stringify(/nop/.exec(str)); //true
//e2 ... e4 //true
e5=JSON.stringify(str.match(/(ab)a/))===JSON.stringify(/(ab)a/.exec(str)); //true

.Exec () समारोह regexp.exec(str)निम्न करेगा:

  • अगर वहाँ है एक मैच में वापस कर देंगे:
    • यदि gध्वज का उपयोग regexp में किया जाता है: यह अगले मैच के लिए लौटेगा (प्रत्येक बार इसे कहा जाता है) : जरूरी:[N_MatchedStr, N_Captured1, N_Captured2, ...]N यह अगले मैच में आगे नहीं बढ़ेगा यदि regexp ऑब्जेक्ट को एक चर में संग्रहीत नहीं किया जाता है (इसे उसी वस्तु की आवश्यकता है)
    • यदि gध्वज को regexp में उपयोग नहीं किया जाता है: यह उसी तरह लौटेगा जैसे कि इसका gध्वज था और पहली बार और केवल एक बार बुलाया गया था।
  • अगर कोई मैच नहीं है तो वह वापस आ जाएगी:
    • null

.Exec का उदाहरण () ( gफ्लैग का उपयोग करके संग्रहीत रेगेक्स + ( यह प्रत्येक कॉल के साथ बदलता है)):

var str = "qqqABApppabacccaba";
var myexec, rgxp = /(ab)a/gi;

myexec = rgxp.exec(str);
console.log(myexec); //["ABA", "AB"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "ab"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "ab"]
myexec = rgxp.exec(str);
console.log(myexec); //null

//But in this case you should use a loop:
var mtch, myRe = /(ab)a/gi;
while(mtch = myRe.exec(str)){ //infinite looping with direct regexps: /(ab)a/gi.exec()
    console.log("elm: "+mtch[0]+" all: "+mtch+" indx: "+myRe.lastIndex);
    //1st iteration = elm: "ABA" all: ["ABA", "AB"] indx: 6
    //2nd iteration = elm: "aba" all: ["aba", "ab"] indx: 12
    //3rd iteration = elm: "aba" all: ["aba", "ab"] indx: 18
}

प्रत्येक कॉल के साथ परिवर्तित नहीं होने पर .exec () के उदाहरण :

var str = "qqqABApppabacccaba", myexec, myexec2;

//doesn't go into the next one because no g flag
var rgxp = /(a)(ba)/;
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "a", "ba"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "a", "ba"]
//... ["aba", "a", "ba"]

//doesn't go into the next one because direct regexp
myexec2 = /(ab)a/gi.exec(str);
console.log(myexec2); //["ABA", "AB"]
myexec2 = /(ab)a/gi.exec(str);
console.log(myexec2); //["ABA", "AB"]
//... ["ABA", "AB"]

1

कभी कभी regex.exec () ले जाएगा बहुत अधिक समय तो string.match ()।

यह उल्लेख के लायक है कि अगर string.match () और regex.exec () के परिणाम समान हैं (उदाहरण: जब \ g ध्वज का उपयोग नहीं कर रहे हैं), regex.exec () x2 से x30 या स्ट्रिंग के बीच कहीं ले जाएगा। से मेल ():

इसलिए ऐसे मामलों में, "नए RegExp () (एग्ज़िक्यूट) (") के दृष्टिकोण का उपयोग केवल तभी किया जाना चाहिए जब आपको एक वैश्विक रेगेक्स (यानी एक से अधिक बार निष्पादित करने के लिए) की आवश्यकता हो।


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