2012-05-09 6 views
6

अभिव्यक्ति है:मैं इस बैकस-नौर फॉर्म अभिव्यक्ति को Regex (.Net) में कैसे बदल सकता हूं?

N | (1 { A | B | C | D | E1 | E2 | E3 }) 

वर्णनकर्ता "एन" या बिना दोहराव के एक या एक से सूचीबद्ध वर्णनकर्ता के और अधिक मतलब।

सबसे अच्छा मुझे मिल गया है:

@"^(N|(A|B|C|D|E1|E2|E3){1,})$" 

लेकिन उस पुनरावृत्ति को रोकने नहीं करता है।

@"^(N|(A{0,1}B{0,1}...)$" 

जो पुनरावृत्ति को रोकता है लेकिन उसके बाद तत्वों के लिए एक विशिष्ट क्रम की आवश्यकता होती है, जो वास्तव में ठीक नहीं है।

कोई विचार?

(मैं वास्तव में लगता है कि BNF अभिव्यक्ति ही पुनरावृत्ति की अनुमति नहीं देता नहीं हूँ, लेकिन है कि मैं क्या जरूरत है।)

+0

http://kore-nordmann.de/blog/do_NOT_parse_using_regexp.html शब्दों को पहचानने के लिए नियमित अभिव्यक्तियों का उपयोग करें, संरचनाओं पर नहीं। –

+0

मुझे लगता है कि समझ में आता है। लेकिन मैं इस संरचना को पहचानने के लिए क्या उपयोग करूंगा? @ डेविडब्रैबेंट इसका उपयोग उल्लिखित फॉर्म के इनपुट को प्रमाणित करने के लिए किया जाएगा। – Daniel

+0

या पीसीआरई विधि है जिसका आप सुझाव दे रहे हैं? – Daniel

उत्तर

4

, आप कर सकते हैं, लेकिन यह काफी नहीं है:

Regex regexObj = new Regex(
    @"^   # Start of string 
    (?:   # Either match... 
    N   # N 
    |    # or... 
    (?:   # Match one of the following: 
     A(?!.*A) # A unless followed somewhere later by another A 
    |   # or 
     B(?!.*B) # B unless... 
    |   # etc. etc. 
     C(?!.*C) 
    | 
     D(?!.*D) 
    | 
     E1(?!.*E1) 
    | 
     E2(?!.*E2) 
    | 
     E3(?!.*E3) 
    )+   # one or more times 
    )    # End of alternation 
    $    # End of string", 
    RegexOptions.IgnorePatternWhitespace); 

यह समाधान negative lookahead assertions उपयोग करता है।

+0

अच्छा, धन्यवाद! – Daniel

+0

बस एक सवाल @Tim। '?:' क्या काम करता है? ऐसा लगता है कि उन दोनों के बिना काम कर रहा है। – Daniel

+0

@ डैनियल: केवल अंतर यह है कि '(...) 'एक * कैप्चरिंग * समूह है, जिसका अर्थ है कि रेगेक्स इंजन उस समूह के अंदर जो कुछ भी मेल खाता था, उसे बैकरेफर में संग्रहीत करता है जिसे आप बाद में संदर्भित कर सकते हैं। यदि आपको ऐसा करने की आवश्यकता नहीं है, तो '(?: ...)' वही काम करता है, लेकिन मैच के उस हिस्से को संग्रहीत किए बिना। इसलिए, वे थोड़ा अधिक कुशल हैं। –

1

मैं भी एक .net Regex के लिए यकीन है कि यह संभव है नहीं कर रहा हूँ (जो भी ज्यादा शक्तिशाली है ऐसा करने के लिए 'नियमित भाषा' की सख्त परिभाषा);

bool IsValid(string input) 
{ 
    var Ns = input.Count(c => c == 'N'); 
    var As = input.Count(c => c == 'A'); 
    // etc 
    var E1s = Regex.Matches(input, "E1").Count 
    // etc 

    var maxDescriptorCount = (new[] { As, ... ,E1s, ... }).Max(); 

    var isValid = 
     ((Ns == 1) && (maxDescriptorCount == 0)) 
     || 
     ((Ns == 0) && (maxDescriptorCount == 1)) 
     ; 

    return isValid; 
} 

यह कम से कम कोड है कि समस्या का हल है: और वैसे भी, जब तक आप एक आवश्यकता केवल एक Regex उपयोग करने के लिए है, तो गलत (मेरे विचार से) के साथ कुछ भी नहीं है? नहीं। क्या यह पठनीय और रखरखाव योग्य है? मुझे ऐसा लगता है।

खैर (आप हस्ताक्षर int MaxN(params int[] numbers) के साथ एक उपयोगिता विधि लिख सकता है अगर आप चाहते थे)

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