سؤال

إذا كنت تكتب برنامجًا قابلاً للتنفيذ من سطر الأوامر، فغالبًا ما تريد أن تقدم للمستخدم عدة خيارات أو إشارات، بالإضافة إلى أكثر من وسيطة واحدة.لقد تعثرت في طريقي عدة مرات، ولكن هل هناك نوع من نمط التصميم للتكرار عبر الوسيطات واستدعاء وظائف المعالج المناسبة؟

يعتبر:

myprogram -f filename -d directory -r regex

كيف يمكنك تنظيم وظائف المعالج بعد استرداد الوسائط باستخدام أي شيء مضمن للغتك؟(نرحب بالإجابات الخاصة باللغة، إذا كان ذلك يساعدك على توضيح الإجابة)

هل كانت مفيدة؟

المحلول

لا أعرف أي "أنماط" موثقة للمعالجة.

أعتقد أن إحدى أقدم المكتبات/واجهات برمجة التطبيقات للتعامل مع الوسائط هي getopt.يُظهر البحث في Google "getopt" الكثير من الصفحات الإرشادية والروابط للتطبيقات.

بشكل عام، لدي خدمة تفضيلات أو إعدادات في تطبيقي يعرف معالج الوسائط كيفية التواصل معها.تتم بعد ذلك ترجمة الوسائط إلى شيء في هذه الخدمة يقوم التطبيق بالاستعلام عنه بعد ذلك.يمكن أن يكون هذا بسيطًا مثل قاموس الإعدادات (مثل إعداد سلسلة يسمى "اسم الملف").

نصائح أخرى

أعتقد أن الإجابة التالية تتوافق أكثر مع ما تبحث عنه:

يجب أن تنظر إلى تطبيق نمط القالب (طريقة القالب في "أنماط التصميم" [جاما، العال])

باختصار، تبدو المعالجة الشاملة كما يلي:

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 التي تحتوي على طرق من أجل:

PreProcess()
ProcessLine()
PostProcess()
Usage()
Main()

ثم قم بإنشاء هيكل يقوم بإنشاء مثيل ConsoleEngine() ويرسل رسالة Main() لبدء تشغيله.

لرؤية مثال جيد لكيفية تطبيق ذلك على وحدة التحكم أو برنامج سطر الأوامر، راجع الرابط التالي:http://msdn.microsoft.com/en-us/magazine/cc164014.aspx

المثال موجود في لغة C#، ولكن الأفكار يمكن تنفيذها بسهولة في أي بيئة أخرى.

ستنظر إلى GetOpt() على أنه الجزء الذي يتناسب مع معالجة الوسيطة (المعالجة المسبقة).

أتمنى أن يساعدك هذا.

لم تذكر اللغة، لكننا أحببنا لغة Java أباتشي كومنز سطر الأوامر.بالنسبة لـ C/C++، استخدم getopt.

بعض التعليقات على هذا...

أولاً، على الرغم من عدم وجود أي أنماط في حد ذاتها، فإن كتابة المحلل اللغوي هي في الأساس تمرين ميكانيكي، نظرًا لأنه بالنظر إلى القواعد النحوية، يمكن إنشاء المحلل اللغوي بسهولة.تتبادر إلى الذهن أدوات مثل Bison وANTLR.

ومع ذلك، فإن المولدات المحللة عادة ما تكون مبالغة في استخدام سطر الأوامر.لذا فإن النمط المعتاد هو أن تكتب واحدًا بنفسك (كما أثبت الآخرون) عدة مرات حتى تمل من التعامل مع التفاصيل المملة وتجد مكتبة للقيام بذلك نيابةً عنك.

لقد كتبت واحدًا لـ C++ يوفر مجموعة من الجهد الذي يقدمه getopt ويستفيد بشكل جيد من القوالب: TCLAP

حسنًا، إنها مشاركة قديمة ولكني ما زلت أرغب في المساهمة.كان المقصود من السؤال اختيار أنماط التصميم، لكن يمكنني رؤية الكثير من النقاش حول المكتبة التي يجب استخدامها.لقد قمت بمراجعة رابط Microsoft وفقًا لـ Lindsay الذي يتحدث عن نمط تصميم القالب المطلوب استخدامه.

ومع ذلك فأنا غير مقتنع بهذا المنشور.الغرض من نمط القالب هو تحديد القالب الذي سيتم تنفيذه بواسطة فئات أخرى مختلفة للحصول على سلوك موحد.لا أعتقد أن تحليل سطر الأوامر يناسبه.

أفضّل استخدام نمط التصميم "Command".هذا النمط هو الأنسب للخيارات القائمة على القائمة.

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

لذلك في حالتك، تصبح جميع -f و -d و -r أوامر ذات جهاز استقبال مشترك أو منفصل محدد.وبهذه الطريقة يمكن تحديد المزيد من أجهزة الاستقبال في المستقبل.ستكون الخطوة التالية هي ربط مسؤوليات الأوامر هذه، في حالة الحاجة إلى سلسلة معالجة.الذي سأختاره.

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

أعتقد أن الجمع بين هذين الاثنين هو الأفضل لتنظيم التعليمات البرمجية لمعالجة سطر الأوامر أو أي نهج قائم على القائمة.

ال دفعة::program_options تعد المكتبة رائعة إذا كنت تستخدم لغة C++ وتتمتع برفاهية استخدام Boost.

بافتراض أن لديك كائن "config" تهدف إلى إعداده باستخدام العلامات ومحلل سطر أوامر مناسب يعتني بتحليل سطر الأوامر ويوفر دفقًا مستمرًا من الخيارات، فهنا تظهر كتلة من الكود الزائف

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;
    }
}

أفضّل خيارات مثل "-t text" و"-i 44"؛لا أحب "-fname" أو "--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);
   }

أنا أستمتع بإجابة ANTLR بواسطة mes5k.هذا رابط إلى Codeproject مخصص لمقالة تناقش ANLTR واستخدام نمط الزيارة لتنفيذ الإجراءات التي تريد من التطبيق أن يتخذها.انها مكتوبة بشكل جيد وتستحق المراجعة.

أوصي باستخدام مكتبة معالج سطر الأوامر. بعض الرجل الروسي خلقت واحدة لائقة، ولكن هناك الكثير منهم هناك.سيوفر لك بعض الوقت حتى تتمكن من التركيز على الغرض من تطبيقك بدلاً من تحليل مفاتيح سطر الأوامر!

Getopt هو السبيل الوحيد للذهاب.

http://sourceforge.net/projects/csharpoptparse

ماذا عن نمط المترجم؟http://www.dofactory.com/net/interpreter-design-pattern

لم تذكر لغة لهذا ولكن إذا كنت تبحث عن غلاف Objective-C لطيف حقًا حول getopt، فإن إطار عمل Dave Dribin's DDCLI لطيف حقًا.

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

انا استعمل ال Getopts::std و احصل على::طويل في بيرل وأيضا جيتوبت وظيفة في C.يؤدي هذا إلى توحيد تحليل وتنسيق المعلمات.اللغات الأخرى لديها آليات مختلفة للتعامل معها.

أتمنى أن يساعدك هذا

عادةً ما يتبع التصميم القياسي ما يفعله getopt، فهناك مكتبات getopt للعديد من اللغات، .NET، وpython، وC، وPerl، وPHP، وما إلى ذلك.

التصميم الأساسي هو أن يكون لديك محلل سطر أوامر يقوم بإرجاع الوسيطات التي تم تمريرها جزءًا تلو الآخر ليتم التحقق منها في حلقة.

هذا المقال يناقش ذلك بمزيد من التفصيل.

أنا لست مهتمًا كثيرًا بالمكتبات، رغم أن ذلك مفيد بالتأكيد.كنت أبحث أكثر عن بعض "الرموز الزائفة" التي توضح معالجة مجموعة الأعلام المتوسطة ومجموعة من الوسائط الأطول، على سبيل المثال.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top