2008-09-10 20 views
38

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

पर विचार करें:

myprogram -f filename -d directory -r regex 

कैसे आप अपनी भाषा के लिए जो कुछ भी बनाया-इन का उपयोग कर बहस को पुनः प्राप्त करने के बाद आप कोड को व्यवस्थित करते हैं? (भाषा-विशिष्ट उत्तरों का स्वागत है, अगर यह आपको उत्तर देने में मदद करता है)

+0

इसे "भाषा-अज्ञेयवादी" के रूप में टैग किया जाना चाहिए क्योंकि सवाल एक डिजाइन पैटर्न के साथ-साथ सुझावों के लिए भी पूछ रहा है। – martinatime

उत्तर

13

मुझे प्रसंस्करण के लिए किसी भी दस्तावेज "पैटर्न" के बारे में पता नहीं है।

मुझे विश्वास है कि तर्कों को संभालने के लिए सबसे पुरानी पुस्तकालयों/एपीआई में से एक है getopt। गुगलिंग "गेटोपेट" कई सारे पेज पेज और कार्यान्वयन के लिंक दिखाती है।

आम तौर पर, मेरे आवेदन में मेरी प्राथमिकताएं या सेटिंग्स सेवा है कि तर्क प्रोसेसर जानता है कि कैसे संवाद करना है। इसके बाद तर्कों को इस सेवा में कुछ में अनुवाद किया जाता है जो तब क्वेरी से आवेदन होता है। यह सेटिंग्स के शब्दकोश के रूप में सरल हो सकता है (जैसे "फ़ाइल नाम" नामक एक स्ट्रिंग सेटिंग)।

1

मैं एक कमांड लाइन प्रोसेसर लाइब्रेरी का उपयोग करने की सलाह दूंगा। Some Russian guy ने एक सभ्य बनाया, लेकिन उनमें से बहुत से लोग वहां हैं। आपको कुछ समय बचाएगा ताकि आप कमांड लाइन स्विच को पार्स करने के बजाय अपने ऐप के उद्देश्य पर ध्यान केंद्रित कर सकें!

+0

मुझे यह लेख पसंद है। धन्यवाद! :-) – craigmoliver

5

आपने भाषा का उल्लेख नहीं किया है, लेकिन जावा के लिए हमें Apache Commons CLI पसंद आया है। सी/सी ++ के लिए, getopt।

0

आप इस के लिए एक भाषा का उल्लेख नहीं है, लेकिन आप देख रहे हैं getopt के चारों ओर एक वास्तव में अच्छा ऑब्जेक्टिव-सी आवरण के लिए तो डेव Dribin के DDCLI ढांचे वास्तव में अच्छा है।

http://www.dribin.org/dave/blog/archives/2008/04/29/ddcli

0

मैं पर्ल में Getopts::std और Getopts::long का उपयोग करें और यह भी सी में Getopt समारोह इस पार्स करने और मापदंडों का प्रारूप standardises। इन भाषाओं को संभालने के लिए अन्य भाषाओं में अलग-अलग तंत्र हैं।

आशा इस मदद करता है

0

मानक डिजाइन आमतौर पर इस प्रकार getopt क्या करता है, कई भाषाओं, .नेट, अजगर, सी, पर्ल, पीएचपी, आदि

मूल डिजाइन करने के लिए है के लिए getopt पुस्तकालयों देखते हैं एक कमांड लाइन पार्सर है जो एक लूप में चेक किए गए तर्कों के भाग से भाग लेता है।

This आलेख इसे और अधिक विस्तार से चर्चा करता है।

2

boost::program_options पुस्तकालय अच्छा होगा यदि आप सी में हैं ++ और बूस्ट का उपयोग कर के लक्जरी है।

+0

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

0

मैं, के रूप में पुस्तकालयों में ज्यादा दिलचस्पी नहीं है कि हालांकि निश्चित रूप से उपयोगी है।मैं कुछ "छद्म कोड" के लिए और अधिक देख रहा था जो उदाहरण के रूप में झंडे के अपने औसत समूह और लंबे तर्कों का एक गुच्छा कहने की प्रसंस्करण को दर्शाता है।

+0

आप स्पष्टीकरण के बारे में यहां अपने प्रश्न में इसे अपडेट करना चाहते हैं। यह केवल जवाब के लिए है। – rpattabi

2

मान लें कि आपके पास एक "कॉन्फ़िगरेशन" ऑब्जेक्ट है जिसका लक्ष्य है कि आप झंडे और उपयुक्त कमांड लाइन पार्सर के साथ सेटअप करना चाहते हैं जो कमांड लाइन को पार्स करने और विकल्पों की निरंतर स्ट्रीम की आपूर्ति करने का ख्याल रखता है, यहां छद्म कोड

का एक ब्लॉक चला जाता है
while (current_argument = cli_parser_next()) { 
    switch(current_argument) { 
     case "f": //Parser strips the dashes 
     case "force": 
      config->force = true; 
      break; 
     case "d": 
     case "delete": 
      config->delete = true; 
      break; 
     //So on and so forth 
     default: 
      printUsage(); 
      exit; 
    } 
} 
2

मुझे "-t text" और "-i 44" जैसे विकल्प पसंद हैं; मुझे "-फनाम" या "--very-long-argument = some_value" पसंद नहीं है।

और "-?", "-h", और "/ h" सभी एक सहायता स्क्रीन उत्पन्न करते हैं।

यहाँ कैसे मेरे कोड दिखाई देता है:

इस पर
int main (int argc, char *argv[]) 
    { int i; 
     char *Arg; 
     int ParamX, ParamY; 
     char *Text, *Primary; 

    // Initialize... 
    ParamX = 1; 
    ParamY = 0; 
    Text = NULL; 
    Primary = NULL; 

    // For each argument... 
    for (i = 0; i < argc; i++) 
     { 
     // Get the next argument and see what it is 
     Arg = argv[i]; 
     switch (Arg[0]) 
     { 
     case '-': 
     case '/': 
      // It's an argument; which one? 
      switch (Arg[1]) 
       { 
       case '?': 
       case 'h': 
       case 'H': 
        // A cry for help 
        printf ("Usage: whatever...\n\n"); 
        return (0); 
        break; 

       case 't': 
       case 'T': 
        // Param T requires a value; is it there? 
        i++; 
        if (i >= argc) 
        { 
        printf ("Error: missing value after '%s'.\n\n", Arg); 
        return (1); 
        } 

        // Just remember this 
        Text = Arg; 

        break; 

       case 'x': 
       case 'X': 
        // Param X requires a value; is it there? 
        i++; 
        if (i >= argc) 
        { 
        printf ("Error: missing value after '%s'.\n\n", Arg); 
        return (1); 
        } 

        // The value is there; get it and convert it to an int (1..10) 
        Arg = argv[i]; 
        ParamX = atoi (Arg); 
        if ((ParamX == 0) || (ParamX > 10)) 
        { 
        printf ("Error: invalid value for '%s'; must be between 1 and 10.\n\n", Arg); 
        return (1); 
        } 

        break; 

       case 'y': 
       case 'Y': 
        // Param Y doesn't expect a value after it 
        ParamY = 1; 
        break; 

       default: 
        // Unexpected argument 
        printf ("Error: unexpected parameter '%s'; type 'command -?' for help.\n\n", Arg); 
        return (1); 
        break; 
       } 

      break; 

     default: 
      // It's not a switch that begins with '-' or '/', so it's the primary option 
      Primary = Arg; 

      break; 
     } 
     } 

    // Done 
    return (0); 
    } 
4

कुछ टिप्पणियां ...

पहले, जबकि वहाँ किसी भी पैटर्न से प्रति, एक पार्सर लेखन अनिवार्य रूप से एक यांत्रिक व्यायाम है नहीं कर रहे हैं, चूंकि व्याकरण दिया जाता है, इसलिए एक पार्सर आसानी से उत्पन्न किया जा सकता है। बाइसन जैसे उपकरण, और एएनटीएलआर दिमाग में आते हैं।

यह कहा गया है कि पार्सर जेनरेटर आमतौर पर कमांड लाइन के लिए ओवरकिल होते हैं। तो सामान्य पैटर्न एक खुद को लिखना है (जैसा कि दूसरों ने दिखाया है) कुछ बार जब तक आप कठिन जानकारी से निपटने में बीमार नहीं हो जाते हैं और पुस्तकालय को आपके लिए ऐसा करने के लिए पाते हैं। TCLAP

+0

'' TCLAP'' एक शानदार सीएलआई पार्सिंग लाइब्रेरी है। 'Argv'' के पार्सिंग के नियमों और पोस्ट-पार्स निष्कर्षण के प्री-पार्स सेटअप बहुत उपयोगी, अंतर्ज्ञानी हैं और प्रोग्राम को सही असतत घटकों (आईएमएचओ) में तोड़ने में मदद करता है। कार्यान्वयन के बजाय अवधारणाओं को चिपकाने के लिए – Sean

2

मैं mes5k द्वारा ANTLR जवाब पर riffing हूँ:

मैं सी के लिए एक ++ कि प्रयास है कि प्रदान getopt का एक समूह की बचत होती है और टेम्पलेट्स के लिए अच्छा उपयोग करता है लिखा था। यह link to Codeproject एक ऐसे लेख के लिए है जो एएनएलटीआर पर चर्चा करता है और उन क्रियाओं को लागू करने के लिए विज़िट पैटर्न का उपयोग करता है, जिन्हें आप चाहते हैं कि आप ऐप ले लें। यह अच्छी तरह लिखित और मूल्यवान समीक्षा है।

12

मुझे लगता है कि निम्नलिखित जवाब की तर्ज पर अधिक है क्या आप देख रहे हैं:

आप टैम्पलेट पैटर्न लागू करने पर गौर करना चाहिए ("डिजाइन पैटर्न" में टेम्पलेट विधि [गामा, एल अल])

संक्षेप में यह है समग्र प्रसंस्करण इस तरह दिखता है:

:

If the arguments to the program are valid then 
    Do necessary pre-processing 
    For every line in the input 
     Do necessary input processing 
    Do necessary post-processing 
Otherwise 
    Show the user a friendly usage message 

संक्षेप में, एक ConsoleEngineBase वर्ग है के लिए तरीकों को लागू

फिर एक चेसिस बनाएं, जो एक ConsoleEngine() उदाहरण को तुरंत चालू करता है और मुख्य() संदेश को इसे बंद करने के लिए भेजता है।

कैसे एक कंसोल या कमांड लाइन कार्यक्रम को यह लागू करने के लिए एक अच्छा उदाहरण देखने के लिए नीचे दिए गए लिंक की जाँच: http://msdn.microsoft.com/en-us/magazine/cc164014.aspx

उदाहरण सी # में है, लेकिन विचारों को आसानी से किसी भी अन्य वातावरण में लागू किया जाता है।

आप GetOpt() को केवल उस भाग के रूप में देखेंगे जो तर्क हैंडलिंग (प्री-प्रोसेसिंग) में फिट है।

उम्मीद है कि इससे मदद मिलती है।

+1

ऊपर उठाया गया। मुझे लगता है कि यह चुना गया जवाब होना चाहिए था। – Plasmarob

3

अच्छा, यह एक पुरानी पोस्ट है लेकिन मैं अभी भी योगदान देना चाहता हूं।सवाल डिजाइन पैटर्न की पसंद पर था, हालांकि मैं पुस्तकालय का उपयोग करने के लिए बहुत सी चर्चा देख सकता था। मैंने लिंडसे के अनुसार माइक्रोसॉफ़्ट लिंक की जांच की है जो उपयोग करने के लिए टेम्पलेट डिजाइन पैटर्न के बारे में बात करता है।

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

मैं बजाय "कमांड" डिज़ाइन पैटर्न के साथ जाऊंगा। यह पैटर्न मेनू संचालित विकल्पों के लिए सबसे अच्छा है।

http://www.blackwasp.co.uk/Command.aspx

अपने मामले, -f में

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

http://www.blackwasp.co.uk/ChainOfResponsibility.aspx

मुझे लगता है कि इन दोनों का संयोजन सबसे अच्छा कमांड लाइन प्रसंस्करण या किसी मेनू आधारित दृष्टिकोण के लिए कोड का आयोजन कर रहे हैं।

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