2009-05-12 11 views
20

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

http://zijab.blogspot.com/2008/09/finding-opposite-of-regular-expression.html कहा गया है कि आप

/^((?!^ MYREGEX).)*$/ 

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

/[a|b]./ 

, स्ट्रिंग "abc" दोनों मेरे regex और बातचीत zijab ने सुझाव दिया साथ झूठी देता है,

/^((?!^[a|b].).)*$/ 

। क्या रेगेक्स के बातचीत को लिखना संभव है, या क्या मैं गलत तरीके से सोच रहा हूं?

+1

कौन सा regex पैकेज आप उपयोग कर रहे हैं (जो भाषा आप काम कर रहे हैं में)? यदि आपका रेगेक्स पैकेज काफी आधुनिक पीसीआरई (पर्ल-संगत RegEx) पैकेज का समर्थन नहीं करता है, तो हो सकता है कि यह ज़िजाब के उदाहरण (शून्य-चौड़ाई नकारात्मक लुकहेड) को गलत व्याख्या कर रहा हो। –

उत्तर

6

कारण अपने उल्टे regex काम नहीं कर रहा '^' अंदर नकारात्मक अग्रदर्शी की वजह से है:

/^((?!^[ab].).)*$/ 
    ^   # WRONG 

शायद यह vim में अलग है, लेकिन हर regex स्वाद में मैं से परिचित हूँ, कैरेट स्ट्रिंग की शुरुआत से मेल खाता है (या मल्टीलाइन मोड में एक लाइन की शुरुआत)। लेकिन मुझे लगता है कि ब्लॉग एंट्री में सिर्फ एक टाइपो था।

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

"abc" =~ /[ab]./ 

लेकिन जावा में, यह नहीं है:

"abc".matches("[ab].") 

क्योंकि regex matches() विधि के लिए पारित परोक्ष दोनों सिरों पर लंगर डाले है है कि (यानी , /^[ab].$/)।

अधिक आम लेना, पर्ल अर्थशास्त्र, /[ab]./ का अर्थ है कि लक्ष्य स्ट्रिंग में एक 'ए' या 'बी' होता है जिसके बाद कम से कम एक (गैर-रेखा विभाजक) वर्ण होता है। दूसरे शब्दों में, किसी भी बिंदु पर, स्थिति सत्य है। उस वक्तव्य के विपरीत, हर बिंदु पर स्थिति गलत है। इसका मतलब है कि, इससे पहले कि आप हर किरदार के उपभोग करते हैं, आप पुष्टि करते हैं कि चरित्र एक मिलान अनुक्रम की शुरुआत नहीं है एक नकारात्मक अग्रदर्शी करते हैं:

(?![ab].). 

और इसलिए regex है आप, जांच करने के लिए हर चरित्र है दोनों सिरों पर टिका होना करने के लिए:

/^(?:(?![ab].).)*$/ 

सामान्य उपाय दिया गया है कि, लेकिन मैं इसे को उलटने के लिए हर regex संभव है नहीं लगता है - जब नहीं मूल regexes सकारात्मक और नकारात्मक lookarounds, अनिच्छुक और अधिकार शामिल कर सकते हैं क्वांटिफायर, और कौन जानता है s-क्या।

11

क्या आप अभी यह देखने के लिए जांच नहीं सकते कि कोई मिलान नहीं है? मुझे नहीं पता कि आप किस भाषा का उपयोग कर रहे हैं, लेकिन इस छद्म कोड के बारे में कैसे?

if (!'Some String'.match(someRegularExpression)) 
    // do something... 

आप केवल regex को बदल सकते हैं, तो आप अपने लिंक से मिला काम करना चाहिए:

/^((?!REGULAR_EXPRESSION_HERE).)*$/ 
+1

ठीक है, यह समस्या है। मैं regexes या कोड लिख नहीं रहा हूँ। मेरे पास एक ऐप है जो लोगों को अपने स्वयं के रेगेक्स में प्रवेश करने देता है, और उन्हें या तो समावेशी या अनन्य होना चाहिए। मुझे या तो उन्हें डेटा के दूसरे भाग में शामिल करने की आवश्यकता है - समावेशी/अनन्य, या उन्हें एक 'विपरीत' पैटर्न का उपयोग करके, सभी समावेशी या अनन्य लिखने के लिए मजबूर करें, यदि कोई मौजूद है।इसका उपयोग केवल प्रोग्रामर द्वारा किया जाएगा, इसलिए जटिलता चिंता का विषय नहीं है - बस संभावना है। – Greg

+1

हम्म, मैं देखता हूं। तो यह क्यों काम नहीं करता है? /^((?!REGULAR_EXPRESSION_HERE).)*$/ (आपके लिंक से लिया गया।) यह मेरे लिए काम करता है। –

5

आप चरित्र शुरू ([^…]) में ^ लिख कर सेट को उलटने के कर सकते हैं। तो [ab] की विपरीत अभिव्यक्ति (a या b से मिलान करें) [^ab] है (न तो a और न ही b)।

लेकिन आपकी अभिव्यक्ति जितनी अधिक जटिल हो जाती है, उतनी जटिल पूरक अभिव्यक्ति भी होती है। एक उदाहरण:

आप शाब्दिक foo से मेल खाना चाहते हैं। एक अभिव्यक्ति, कुछ और से मेल करता है कि लेकिन एक स्ट्रिंग है foo शामिल होता है मिलान करने के लिए या तो

  1. से कम foo (^.{0,2}$), या
  2. किसी भी तीन पात्रों लंबी स्ट्रिंग है कि कोई भी स्ट्रिंग कि foo नहीं है (^([^f]..|f[^o].|fo[^o])$) , या
  3. अब कोई स्ट्रिंग जिसमें foo नहीं है।

सभी एक साथ इस काम कर सकते हैं:

^[^fo]*(f+($|[^o]|o($|[^fo]*)))*$ 

लेकिन नोट: यह केवल foo पर लागू होता है।

2

तुम भी re.split का उपयोग करके इस (अजगर में) कर सकते हैं, और अपने नियमित अभिव्यक्ति के आधार पर बंटवारे, इस प्रकार सभी भागों है कि रेगुलर एक्सप्रेशन से मेल नहीं है, how to find the converse of a regex

1

पर्ल में आप कर सकते हैं विरोधी मैच लौटने $string !~ /regex/; के साथ।

0

grep के साथ, आप --invert-match या -v का उपयोग कर सकते हैं।

0

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

यह प्रतिद्वंद्वी दिखता है, लेकिन काम करता है।

जैसे (foo)?+.+bar, foox और xfoo से मेल खाता है, लेकिन foo (या एक खाली स्ट्रिंग) से मेल नहीं होगा।

यह अन्य बोलियों में संभव हो सकता है, लेकिन यह अपने आप को काम करने के लिए नहीं मिल सका (वे और अधिक करता है, तो दूसरे मैच में विफल रहता है पीछे करने के लिए तैयार लग रहे हैं?)

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