2010-03-09 9 views
8

मैं इस फ़ाइल का उपयोग किसी फ़ाइल में टैग की सामग्री प्राप्त करने के लिए करता हूं।जावास्क्रिप्ट रेगेक्स लटकता है (v8 का उपयोग करके)

var regex = new RegExp("<tag:main>((?:.|\\s)*)</tag:main>"); 

इससे v8 इंजन अनिश्चित काल तक लटका हुआ है।

अब, अगर मैं new RegExp("<tag:main>([\s\S]*)</tag:main>") का उपयोग करता हूं, तो सब अच्छा है।

किसी को भी पता है कि पहला व्यक्ति कितना लंबा लेता है?

+0

रेगेक्स लटकने या इसे लागू करने का निर्माण? आपके द्वारा पोस्ट की गई लाइन मेरे लिए ठीक काम करती है – cobbal

+0

सृजन लटका नहीं है, केवल परीक्षण या मैच के माध्यम से इसका उपयोग कर रहा है। लंबे तारों का उपयोग – Engwan

+0

क्या आपने एक लालची मैच की कोशिश की है?'var regex = new RegExp (" ((?:। | \\ s) *?) ");'। यदि दस्तावेज़ में एकाधिक टैग तत्व हैं तो आपका regexp समस्याएं पैदा कर सकता है। –

उत्तर

15

अंतिम विनाश </tag:main> टैग के बाद होने वाली रिक्त स्थान के लंबे अनुक्रमों पर यह विनाशकारी बैकट्रैक। उस मामले पर विचार करें जहां विषय स्ट्रिंग 100 रिक्त स्थान के साथ समाप्त होती है। सबसे पहले यह विकल्प के बाईं ओर . के साथ उन सभी से मेल खाता है। यह विफल रहता है क्योंकि कोई बंद टैग नहीं है, इसलिए यह पिछले चरित्र को \s के साथ मिलान करने का प्रयास करता है। यह भी विफल रहता है, इसलिए यह \s और . के रूप में अंतिम स्थान के रूप में दूसरी-से-अंतिम स्थान से मिलान करने का प्रयास करता है। यह विफल रहता है (अभी भी कोई बंद टैग नहीं) इसलिए यह \s के रूप में अंतिम स्थान की कोशिश करता है। जब यह विफल हो जाता है तो यह \s के रूप में तीसरे से अंतिम स्थान से मेल खाता है और पिछले दो रिक्त स्थान से मेल खाने के सभी 4 तरीकों का प्रयास करता है। जब यह विफल हो जाता है तो यह \s के रूप में चौथी-से-आखिरी जगह की कोशिश करता है और पिछले 3 स्थानों पर सभी 8 तरीके। फिर 16, 32 इत्यादि। 100 वीं से आखिरी जगह तक पहुंचने से पहले ब्रह्मांड समाप्त होता है।

विभिन्न वीएम में रेगेक्सपी मैचों के लिए अलग-अलग प्रतिक्रियाएं होती हैं जो आपदाजनक बैकट्रैकिंग के कारण हमेशा के लिए होती हैं। कुछ बस 'नो मैच' की रिपोर्ट करेंगे। वी 8 में यह किसी भी अन्य अनंत या निकट अनंत लूप लिखने जैसा है।

गैर लालची * का उपयोग करते हुए आप क्या चाहते हैं (आप पहले </tag:main> पर रोकने के लिए, पिछले नहीं चाहते हैं), लेकिन अभी भी रिक्त स्थान जहां समापन अनुक्रम याद आ रही है की लंबी तार के लिए घातक बैक ट्रैकिंग करना होगा करेंगे।

यह सुनिश्चित करना कि आंतरिक ब्रैकेट में समान वर्ण वैकल्पिक के दोनों किनारों से मेल नहीं खा सकते हैं, समस्या को एक घातीय से एक तक स्ट्रिंग की लंबाई में रैखिक कर देगा। एक विकल्प के बजाय एक वर्ण वर्ग का प्रयोग करें या वैकल्पिक बार के दाईं ओर \n डालें। \n. से विवादित है, इसलिए यदि आप रिक्त स्थान का लंबा अनुक्रम हिट करते हैं तो regexp इंजन समाप्त होने से पहले सभी बाएं-दाएं-बाएं इत्यादि संयोजनों का प्रयास नहीं करता है।

+0

अच्छी व्याख्या। क्या आपको पता है कि डॉट में \ r भी शामिल है या नहीं? –

+3

@ मार्टिन: जावास्क्रिप्ट में, '.'' [^ \ r \ n \ u2028 \ u2029] ' –

+0

@Alan - के बराबर है! –

3

मुझे लगता है कि यह विनाशकारी रूप से वापस ट्रैकिंग है।

मुझे लगता है कि इस मुद्दे का हिस्सा अच्छी तरह से हो सकता है कि डॉट और पारस्परिक रूप से अनन्य नहीं हैं।

अगर मैं

<tag:main>((?:.|[\r\n])*)</tag:main> 

करने के लिए अपने अभिव्यक्ति बदल सकते हैं और Regex बडी डीबगर में इसे चलाने के लिए यह एक बहुत घटना में जल्दी में विफल रहता है कि परीक्षण स्ट्रिंग मिलान नहीं है।

+0

। \ S सभी पात्रों से मेल खाना है। इसलिये । नई लाइन को छोड़कर सभी पात्रों से मेल खाता है। – Engwan

+0

मुझे नहीं लगता कि यह ऐसा करेगा। मैंने आपके रेगेक्स को रेगेक्सबड्डी में चिपकाया और अपनी टिप्पणी में अपनी टिप्पणी पेड़ चिपका दी। –

+0

आपको RegexBuddy पर पेस्ट करने से पहले अतिरिक्त \ को हटा देना चाहिए। \\ का उपयोग किया जाता है क्योंकि यह RegExp कन्स्ट्रक्टर को पास एक जावास्क्रिप्ट स्ट्रिंग है। – Engwan

0

(?:.|\s)* के बजाय, आप [^]* का उपयोग किसी भी चरित्र से मेल खाने के लिए कर सकते हैं जिसमें न्यूलाइन के विभिन्न रूप शामिल हैं।

कोई विकल्प नहीं है, इसलिए विनाशकारी बैकट्रैकिंग का कोई जोखिम नहीं है।

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