2013-03-08 8 views
11

में जोड़ना मान लें कि मेरे पास नियमित अभिव्यक्तियों की एक सूची है (बाहरी स्रोत - फ़ाइल, डेटाबेस इत्यादि से पढ़ें)। मैं यह जांचना चाहता हूं कि इन नियमित अभिव्यक्तियों में से कौन सा स्ट्रिंग मिलान करता है।एकाधिक नियमित अभिव्यक्तियों को एक automaton

मैं इन सब नियमित अभिव्यक्ति के माध्यम से पुनरावृति बना सकते हैं और उन्हें मेल खाते हैं, लेकिन सूची में एक बहुत बड़ा एक हो सकता है और यह एक महत्वपूर्ण ऑपरेशन है। है, लेकिन फिर समस्या यह है कि मैं केवल सबसे पहले मिलने वाला नियमित अभिव्यक्ति, सभी की पहचान कर सकते हैं |

मैं इन सब नियमित अभिव्यक्ति में (उन दोनों के बीच) के साथ गठजोड़ कर सकते हैं।

एक और विचार इन सभी नियमित अभिव्यक्ति के लिए एक automaton बनाने के लिए और के साथ अंतिम राज्यों चिह्नित करने के लिए, मान लें कि, इसी नियमित अभिव्यक्ति की अनुक्रमित हो सकता है। मैं http://cs.au.dk/~amoeller/automaton/ पर देख रहा था, एक पुस्तकालय जो नियमित अभिव्यक्तियों और automaton के साथ काम करने में सक्षम प्रतीत होता है, लेकिन यह सुनिश्चित नहीं है कि यह मेरी समस्या को हल करने के लिए बढ़ाया जा सके।

क्या आपके पास कोई अन्य विचार है?

एक कोड नमूना कुछ टिप्पणियों को स्पष्ट करने के लिए, मैं जोड़ दिया है:

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 


public class PatternTest { 
    public static void main(String[] args) { 
     Pattern p = Pattern.compile("(a(?:b|c)a)|((?:a|b)ba)|(ab(?:a|c))");  
     Matcher m = p.matcher("aba"); 
     System.out.println(m.matches()); 
     System.out.println(m.groupCount()); 
     for (int i = 0, n = m.groupCount(); i < n; i++) { 
      System.out.println(m.group(i)); 
     } 
    } 
} 

बाहर

true 
3 
aba 
aba 
null 

प्रिंट होगा आप देख सकते हैं केवल पहले समूह मिलान किया जाता है और मैं नहीं दिख रहा है दूसरे दो से मेल खाने का एक तरीका।

अधिक निष्कर्ष - उपरोक्त automaton लाइब्रेरी का उपयोग करके, समस्या निम्न को कम कर देगी: यदि आप दो या अधिक automatons को जोड़ते हैं, तो आप अंतिम स्थिति के लिए कैसे पहचान सकते हैं, जिसमें मूल automatons संबंधित है?

+0

क्या आपने प्रत्येक 'एड एक्सप्रेशन' में नामित समूह जोड़ने पर विचार किया है? आप जांच सकते हैं कि कौन से मैच मेल खाते हैं। –

+0

वे ध्वनि जो आपके पास जावा के लिए हैं। पर्ल में यह आसान होगा। आप बस सभी अभिव्यक्तियों को वैकल्पिक कर सकते हैं, और प्रत्येक अभिव्यक्ति (जिसे 'एक्स' कहा जाता है) के अंत में उदाहरण के लिए जोड़ें (? {$ मिलान {एक्स} = 1}) (?!) '। एक्सचेंज के रूप में अभिव्यक्ति 'एक्स' को चिह्नित करता है, और उसके बाद मैच में विफल रहता है, जिससे अन्य अभिव्यक्तियां भी मिलती हैं। (इसे अनुकूलित करने के लिए आप प्रत्येक अभिव्यक्ति को परमाणु कैप्चरिंग समूह में भी डाल सकते हैं।) – Qtax

+0

@MichaelW: हाँ, मैंने इसे भी माना। समस्या यह है कि जावा में regexp केवल पहले समूह (नाम या अनाम) से मेल खाता है। –

उत्तर

2

dk.brics.automaton सीधे इसका समर्थन नहीं करता है, लेकिन आप विभिन्न प्रकार के स्वीकार्य राज्यों के बीच अंतर करने के लिए ऑटोमाटा (और प्रासंगिक ऑटोमाटा ऑपरेशंस) के प्रतिनिधित्व को सामान्यीकृत कर सकते हैं। एक int फ़ील्ड जोड़कर प्रारंभ करें, उदाहरण के लिए, State कक्षा में और जब भी 'स्वीकार' सेट हो, इस फ़ील्ड का उपयोग करें।

2

एक निश्चित जवाब के लिए (यदि वहाँ एक है) हम कुछ और जानकारी, जैसे की आवश्यकता होगी:

  1. आप कहते हैं कि regexes की सूची बहुत बड़ा है; क्या आप अधिक विशिष्ट हो सकते हैं? हजारों? लाखों? अरबों और अरबों?

  2. इन regexes कौन लिखा था, और वे जानते हैं कि वे क्या कर रहे हैं? सूची में जोड़े जाने से पहले regexes पूरी तरह से परीक्षण किया गया है (सहीता और प्रदर्शन के लिए)?

  3. अपने नमूना कोड में आप matches() विधि का उपयोग करते हैं, जिसके लिए पूरे स्ट्रिंग का वर्णन करने के लिए रेगेक्स की आवश्यकता होती है। यह कार्य करता है जैसे रेगेक्स वास्तव में
    \A(?:(a(?:b|c)a)|((?:a|b)ba)|(ab(?:a|c)))\z
    जो "aba" से मेल खाता है लेकिन "aaba" या "abaa" से मेल नहीं खाता है। यदि आपने जावा पर आने से पहले अन्य टूल या भाषाओं में रेगेक्स का उपयोग किया है, तो यह व्यवहार आपको आश्चर्यचकित कर सकता है। परंपरागत रूप से, स्ट्रिंग को किसी भी स्ट्रिंग के भीतर को स्ट्रिंग के भीतर, शून्य-लंबाई वाले सबस्ट्रिंग का वर्णन करने के लिए हमेशा एक स्ट्रिंग को "रेगेक्स" से कहा जाता है। जावा में उस व्यवहार को प्राप्त करने के लिए, आपको Matcher's find() विधि का उपयोग करना होगा।

  4. क्या कोई सामान्य कारक है जो आप सूची में सभी regexes से बाहर खींच सकते हैं, जैसे न्यूनतम या अधिकतम लंबाई, सामान्य सबस्ट्रिंग्स, या साझा चरित्र सबसेट? उदाहरण के लिए, आपके नमूने पैटर्न में से किसी एक से मेल खाने वाली कोई भी स्ट्रिंग [abc]{3} से मेल खाना चाहिए। यदि वहां हैं, तो हो सकता है कि आप गंभीर मिलान होने से पहले चलाने के लिए फ़िल्टर (शायद regex, शायद नहीं) के आधार पर फ़िल्टर बनाना चाहें।(मैं इस सुझाव है कि नहीं करता है, तो आप पर्ल, जो पहले से ही इस तरह अनुकूलन के साथ Choc एक गुट है का उपयोग कर रहे थे, लेकिन जावा। ☺ थोड़ी सी मदद स्वीकार करने के लिए भी गर्व नहीं है)

लेकिन मैं सुंदर लग रहा है सुरक्षित सलाह देते हैं कि आप उन्हें एक साथ जोड़कर अलग-अलग regexes के साथ जाने के लिए सलाह देते हैं। फ्रेंकनेरेक्स आवश्यक रूप से बेहतर प्रदर्शन नहीं करेगा, और समस्या निवारण यह एक दुःस्वप्न होगा! आप सभी पैटर्न वस्तुओं पूर्व संकलन कर सकते हैं, और आप समय से आगे एक Matcher वस्तु बना सकते हैं और सभी मैचों के लिए यह पुन: उपयोग, इसलिए की तरह कर सकते हैं:

m.reset(s).usePattern(p); 

यहाँ एक demo है। मैं कोई गारंटी नहीं दे सकता (आप अभी भी किसी भी चीज़ के लिए रेगेक्स लिखने की दया पर हैं), लेकिन यदि कोई समाधान संभव है, तो मुझे लगता है कि यह सबसे आशाजनक दृष्टिकोण है।

+0

ग्रेट उत्तर। शायद क्योंकि मैं वही सोच रहा था, लेकिन जोड़ा गया डेमो अच्छा था और मैंने रीसेट (एक्स) कार्यक्षमता के बारे में सीखा जो मैंने पहले नहीं सोचा था। – Omertron

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