2012-12-15 17 views
6

tl; dr जावा में एक रेगेक्स (मिलान करने के लिए, कैप्चरिंग के लिए) में मनमाने ढंग से regexes को जोड़ने/गठबंधन करने का कोई तरीका है?संयोजन (या) मनमाने ढंग से नियमित अभिव्यक्ति


अपने आवेदन में मैं उपयोगकर्ता से दो सूचियां मिली हैं:

  1. नियमित अभिव्यक्ति की सूची
  2. तार

की सूची और मैं उत्पादन के लिए स्ट्रिंग की एक सूची की जरूरत है में (2) जो कि किसी भी नियमित अभिव्यक्ति से मेल नहीं खाते थे (1)।

मेरे पास जगह में स्पष्ट निष्पक्ष कार्यान्वयन है (सभी स्ट्रिंग्स (2) में पुनरावृत्त करें; प्रत्येक स्ट्रिंग (1) में सभी स्ट्रिंग्स को फिर से भरने के लिए; यदि कोई पैटर्न स्ट्रिंग से मेल नहीं खाता है तो उसे वापस सूची में जोड़ दिया जाएगा) लेकिन मैं सोच रहा था कि सभी पैटर्न को एक ही में जोड़ना संभव था और रेगेक्स कंपाइलर ऑप्टिमाइज़ेशन के अवसरों का फायदा उठाए।

रेगेक्स को ओआर-गठबंधन करने का स्पष्ट तरीका स्पष्ट रूप से (regex1)|(regex2)|(regex3)|...|(regexN) है लेकिन मुझे पूरा यकीन है कि यह व्यक्तिगत बातों पर कोई नियंत्रण नहीं है (उदाहरण के लिए वे पीछे/आगे के सभी शिष्टाचार को शामिल कर सकते हैं) संदर्भ)। इसलिए मैं सोच रहा था कि क्या आप जावा में मनमाने ढंग से regexes को गठबंधन करने के लिए एक बेहतर तरीका सुझा सकते हैं।


ध्यान दें: यह केवल ऊपर से गर्भित है, लेकिन मैं इसे स्पष्ट कर देंगे: मैं केवल स्ट्रिंग के खिलाफ मिलान कर रहा हूँ - मैं पर कब्जा समूहों के उत्पादन में उपयोग करने की आवश्यकता नहीं है।

+0

क्या कोई रेगेक्स स्ट्रिंग के केवल एक हिस्से से मेल खाता है या क्या यह पूरी स्ट्रिंग से मेल खाता है? – Tomalak

+0

@ उपयोगकर्ता द्वारा प्रदान किए गए regexes को टोमालक को स्ट्रिंग के हिस्सों से मिलान करने की अनुमति दी जानी चाहिए (विशेष रूप से, निष्पक्ष कार्यान्वयन में मैं कम से कम एक मैच – CAFxX

+0

और क्या देखता हूं यह देखने के लिए 'Matcher.find()' का उपयोग करता हूं। आपको लगता है कि 'regex1 | regex2 | regex3' गलत परिणाम उत्पन्न करता है? क्या आप ऐसी परिस्थिति बना सकते हैं जिसमें यह होगा? – Tomalak

उत्तर

4

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

[संपादित करें: वास्तव में, यह अभी भी समस्या नामित कब्जा समूहों टकरा साथ का कारण होगा। वास्तव में, पैटर्न भी संकलित नहीं होगा, क्योंकि समूह के नामों का पुन: उपयोग नहीं किया जा सकता है।]

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

तो मूल रूप से, प्रत्येक इनपुट पैटर्न के लिए आप एक अद्वितीय पहचानकर्ता बनाते हैं (उदाहरण के लिए आईडी बढ़ाएं)। फिर सबसे कठिन हिस्सा पैटर्न में समूहों को कैप्चर करना ढूंढ रहा है। आप इसे रेगेक्स के साथ नहीं कर पाएंगे। आपको पैटर्न को स्वयं पार्स करना होगा।

  • लें टिप्पणी जब आप में प्रवेश करने और एक चरित्र वर्ग छोड़ देते हैं, क्योंकि अंदर चरित्र वर्गों कोष्ठकों शाब्दिक चरित्र: यहाँ क्या हुआ अगर आप बस पैटर्न स्ट्रिंग के माध्यम से पुनरावृत्ति कर रहे हैं के लिए बाहर देखने के लिए पर कुछ विचार कर रहे हैं।
  • शायद trickiest हिस्सा: सभी खोलने कोष्ठकों कि ?:, ?=, ?!, ?<=, ?<!, ?> द्वारा पीछा कर रहे हैं पर ध्यान न दें।इसके अलावा विकल्प सेटिंग कोष्ठक भी हैं: (?idmsuxU-idmsuxU) या (?idmsux-idmsux:somePatternHere) जो कुछ भी कैप्चर नहीं करते हैं (निश्चित रूप से उन विकल्पों का कोई सबसेट हो सकता है और वे किसी भी क्रम में हो सकते हैं - - भी वैकल्पिक है)।
  • अब आपको केवल शुरुआती कोष्ठक के साथ छोड़ा जाना चाहिए जो या तो एक सामान्य कैप्चरिंग समूह या नाम पर है: (?<name>। सबसे आसान बात उन सभी के साथ व्यवहार करने के लिए हो सकती है - यानी, एक संख्या और एक नाम दोनों (जहां नाम सेट नहीं किया गया है, तो नाम बराबर है)। फिर आप उन सभी को फिर से लिखते हैं जैसे (?<uniqueIdentifier-md5hashOfName> (हाइफ़न वास्तव में नाम का हिस्सा नहीं हो सकता है, आपके पास हैश के बाद आपके वेतन वृद्धि संख्या होगी - क्योंकि हैश निश्चित लंबाई की है, वहां कोई डुप्लीकेट नहीं होगा; बहुत अधिक कम से कम)। यह सुनिश्चित करना सुनिश्चित करें कि मूल रूप से कौन सा नंबर और समूह का नाम था।
  • जब भी आप बैकस्लैश का सामना करते हैं तो वहां तीन विकल्प होते हैं:
    1. अगला वर्ण एक संख्या है। आपके पास एक क्रमांकित बैकरेफर है। उन सभी नंबरों को k<name> से बदलें जहां name समूह के लिए जेनरेट किया गया नया समूह नाम है।
    2. अगले पात्र k<...> हैं। फिर इसे इसी नए नाम से प्रतिस्थापित करें।
    3. अगला चरित्र कुछ और है। इसे छोड़। वह एक ही समय में ब्रांड्स से बचने और बैकस्लाश से बचने से बचता है।
  • मुझे लगता है कि जावा आगे संदर्भों की अनुमति दे सकता है। उस स्थिति में आपको दो पास की जरूरत है। पहले सभी समूहों का नाम बदलने का ख्याल रखना। फिर सभी संदर्भों को बदलें।

एक बार जब आप इसे प्रत्येक इनपुट पैटर्न पर करते हैं, तो आप उन्हें | से सुरक्षित रूप से संयोजित कर सकते हैं। बैकरेक्शंस की तुलना में किसी अन्य सुविधा को इस दृष्टिकोण के साथ समस्या नहीं होनी चाहिए। कम से कम तब तक जब तक आपके पैटर्न मान्य न हों। बेशक, यदि आपके पास a(b और c)d इनपुट हैं तो आपको कोई समस्या है। लेकिन यदि आप यह नहीं देखते हैं कि पैटर्न स्वयं संकलित किए जा सकते हैं तो आप हमेशा ऐसा करेंगे।

मुझे आशा है कि इससे आपको सही दिशा में एक सूचक मिले।

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