2009-10-05 18 views
187

जब मैं वैश्विक ध्वज और केस असंवेदनशील ध्वज का उपयोग करता हूं तो इस नियमित अभिव्यक्ति के साथ क्या समस्या है? प्रश्न उपयोगकर्ता उत्पन्न इनपुट है। परिणाम [सच, सच] होना चाहिए।वैश्विक ध्वज के साथ RegExp गलत परिणाम क्यों देता है?

var query = 'Foo B'; 
var re = new RegExp(query, 'gi'); 
var result = []; 
result.push(re.test('Foo Bar')); 
result.push(re.test('Foo Bar')); 
// result will be [true, false] 

var reg = /^a$/g; 
 
for(i = 0; i++ < 10;) 
 
    console.log(reg.test("a"));

+36

जावास्क्रिप्ट में RegExp के कई जाल में से एक में आपका स्वागत है। यह रीजिक्स प्रसंस्करण के लिए सबसे खराब इंटरफेस में से एक है जिसे मैंने कभी मिले हैं, अजीब साइड इफेक्ट्स और अस्पष्ट चेतावनी से भरा है। आमतौर पर रेगेक्स के साथ आप जो सामान्य कार्य करना चाहते हैं, वे सही वर्तनी करना मुश्किल हैं। – bobince

+0

XRegExp एक अच्छा विकल्प की तरह दिखता है। http://xregexp.com/ – about

+0

यहां उत्तर भी देखें: http://stackoverflow.com/questions/604860/interesting-test-of-javascript-regexp – Prestaul

उत्तर

245

RegExp वस्तु इतनी अनुवर्ती मिलान पर उसे अंतिम बार उपयोग सूचकांक से शुरू होगा जहां एक मैच हुआ lastIndex का ट्रैक रखता है, के बजाय

var query = 'Foo B'; 
var re = new RegExp(query, 'gi'); 
var result = []; 
result.push(re.test('Foo Bar')); 

alert(re.lastIndex); 

result.push(re.test('Foo Bar')); 

आप मैन्युअल रूप से हर परीक्षण के बाद 0 lastIndex पुनर्स्थापित करने के लिए नहीं करना चाहते हैं, बस 0 निकालें: 0. की एक नजर डालेंध्वज।

RegExp.prototype:

यहाँ एल्गोरिथ्म है कि चश्मा हुक्म (खंड 15.10.6.2) है।कार्यकारी (स्ट्रिंग)

निष्पादित करता नियमित अभिव्यक्ति के खिलाफ स्ट्रिंग का एक रेगुलर एक्सप्रेशन मिलान और , या अशक्त मैच के परिणाम रखने वाले अगर स्ट्रिंग (स्ट्रिंग ToString से मेल नहीं खाती किसी सरणी ऑब्जेक्ट

  1. एस ToString (स्ट्रिंग का मान होना) करते हैं: इस प्रकार स्ट्रिंग) नियमित अभिव्यक्ति का एक घटना के लिए खोज की है पैटर्न।
  2. लंबाई लंबाई की लंबाई एस
  3. अंतिम इंडेक्स अंतिम इंडेक्स संपत्ति का मूल्य बनने दें।
  4. मुझे ToInteger (lastIndex) का मान होने दें।
  5. यदि वैश्विक संपत्ति गलत है, तो मुझे = 0.
  6. यदि मैं < 0 या I> लंबाई तो अंतिम इंडेक्स 0 पर सेट करता हूं और शून्य वापस करता हूं।
  7. कॉल [[मैच]], इसे तर्क एस और मैं दे रहा हूं। यदि [[मैच]] विफलता लौटा, चरण 8 पर जाएं; अन्यथा इसके राज्य परिणाम बनें और चरण 10 पर जाएं।
  8. मुझे i = i + 1 दें।
  9. चरण 6 पर जाएं।
  10. ई आर के अंत इंडेक्स मान दें।
  11. यदि वैश्विक संपत्ति सत्य है, तो अंतिम इंडेक्स को ई पर सेट करें।
  12. आर आर कैप्चर सरणी की लंबाई होने दें। (यह 15.10.2.1 के NCapturingParens रूप में एक ही मूल्य है।)
  13. वापसी निम्नलिखित गुणों के साथ एक नई सरणी:
    • सूचकांक संपत्ति भीतर मिलान किया सबस्ट्रिंग की स्थिति के लिए सेट है पूरा स्ट्रिंग एस
    • इनपुट संपत्ति एस
    • को सेट कर दिया जाता लंबाई संपत्ति n + 1.
    • 0 prope के लिए सेट है आरटीई मिलान किए गए सबस्ट्रिंग पर सेट है (यानी। ऑफसेट I समावेशी और ऑफसेट और अनन्य के बीच एस का हिस्सा)।
    • प्रत्येक पूर्णांक के लिए मैं ऐसा करता हूं कि I> 0 और I ≤ n, आरएस कैप्चर सरणी के ith तत्व को ToString (i) से नाम की संपत्ति सेट करें।
+39

यह गैलेक्सी एपीआई डिज़ाइन के लिए हिचिकर गाइड की तरह है। "आप जिस पतन में गिर गए हैं, उसे कई सालों तक पूरी तरह से दस्तावेज किया गया है, अगर आपको केवल" – Retsam

+4

जांचने के लिए परेशान किया गया था, तो फ़ायरफ़ॉक्स का चिपचिपा झंडा ऐसा नहीं करता जो आप बिल्कुल करते हैं। इसके बजाय, यह नियमित अभिव्यक्ति की शुरुआत में^^ था जैसे कि यह^स्ट्रिंग की शुरुआत के बजाय * वर्तमान * स्ट्रिंग स्थिति (अंतिम इंडेक्स) से मेल खाता है। यदि रेगेक्स "आखिरी इंडेक्स के बाद कहीं भी" के बजाय "ठीक है" से मेल खाता है तो आप प्रभावी रूप से परीक्षण कर रहे हैं। आपके द्वारा प्रदान किया गया लिंक देखें! – Doin

+0

इस उत्तर का उद्घाटन वक्तव्य बिल्कुल सटीक नहीं है। आपने कल्पना के चरण 3 को हाइलाइट किया जो कुछ भी नहीं कहता है। 'LastIndex' का वास्तविक प्रभाव चरण 5, 6 और 11 में है। आपका उद्घाटन कथन केवल तभी सच है जब वैश्विक फ़्लैग सेट है। – Prestaul

59

आप एक ही RegExp वस्तु का उपयोग कर रहे हैं और यह कई बार क्रियान्वित। प्रत्येक लगातार निष्पादन पर यह अंतिम मैच सूचकांक से जारी है।

आप प्रत्येक क्रियान्वयन से पहले शुरू से ही शुरू करने के लिए रेगुलर एक्सप्रेशन "रीसेट" की जरूरत है:

result.push(re.test('Foo Bar')); 
re.lastIndex = 0; 
result.push(re.test('Foo Bar')); 
// result is now [true, true] 

कहा करने के बाद इसे और अधिक हर बार (भूमि के ऊपर के रूप में कम से कम है एक नया RegExp ऑब्जेक्ट बनाने के लिए पठनीय हो सकता है कि RegExp वैसे भी कैश किया गया है):

result.push((/Foo B/gi).test(stringA)); 
result.push((/Foo B/gi).test(stringB)); 
32

RegExp.prototype.test अद्यतन करता है नियमित अभिव्यक्ति 'lastIndex संपत्ति इसलिए प्रत्येक कि परीक्षण शुरू होगा जहां अंतिम व्यक्ति बंद हो गया था। मैं के बाद से यह lastIndex संपत्ति को अपडेट नहीं करता String.prototype.match उपयोग करने का सुझाव चाहते हैं:

!!'Foo Bar'.match(re); // -> true 
!!'Foo Bar'.match(re); // -> true 

नोट: !! एक बूलियन में बदल देता है और उसके बाद बूलियन उलट तो यह परिणाम को दर्शाता है।

वैकल्पिक रूप से, तुम सिर्फ lastIndex संपत्ति रीसेट कर सकते हैं:

result.push(re.test('Foo Bar')); 
re.lastIndex = 0; 
result.push(re.test('Foo Bar')); 
9

वैश्विक g झंडा हटाने से आपकी समस्या का समाधान हो।

var re = new RegExp(query, 'gi'); 

होना चाहिए

var re = new RegExp(query, 'i'); 
0

/जी ध्वज का उपयोग करते हुए कहता है यह एक हिट के बाद खोज जारी रखने के लिए।

If the match succeeds, the exec() method returns an array and updates properties of the regular expression object.

अपनी पहली खोज से पहले:

myRegex.lastIndex 
//is 0 

पहले खोज

myRegex.lastIndex 
//is 8 

के बाद छ निकालें और इसे exec की प्रत्येक कॉल के बाद खोज बाहर निकालता है()।

संबंधित मुद्दे