分解复杂的命令行参数

分解复杂的命令行参数
    当我们的程序需要运行在命令行环境下的时候,分解复杂的命令行参数往往成为一件不难但又麻烦的事情。我们经常发现.net的开发工具的命令行格式都是"/parameterA:valueA /parameterB:valueB"。如果我们希望使用这种格式的命令行参数的话,如何分析就成为我们需要解决的一个问题。

    我们可以通过WinMain或者GetCommandLine()来获得一个unicode格式的命令行参数。这个命令行参数是没有被分析过的,一个完整的字符串。首先,我们使用空格分解字符串,不过在遇到双引号的时候,我们忽略空格一直到遇到另一个双引号为止。所以下面的命令行参数:
" e:\Coding\VL++\Tools\KfpCompiler\Debug\KfpCompiler.exe "   / library: " C:\Kernel FP\Library\ "   / output: " C:\Kernel FP\Output\ "   / code: " C:\Kernel FP\Game\Project.kproj "   / print - error  / print - report
    将会被分解成6行:
1  " e:\Coding\VL++\Tools\KfpCompiler\Debug\KfpCompiler.exe "
2  / library: " C:\Kernel FP\Library\ "
3  / output: " C:\Kernel FP\Output\ "
4  / code: " C:\Kernel FP\Game\Project.kproj "
5  / print - error
6  / print - report

    对于每一行的命令,我们可以总结出以下几种格式:
    1、值
    2、/参数
    3、/参数:值
    我们可以规定,如果值的第一个字符和最后一个字符都是双引号的话,那么忽略这两个双引号。我使用Vczh GUI写了一个win32程序显示命令行分析的结果,代码和截图如下:

    首先是程序的代码。这个程序阅读命令行参数之后,将分析结果显示在一个文本框上:
 1  #include  " ..\..\..\Library\Windows\VL_WinGUI.h "
 2 
 3  using   namespace  vl;
 4  using   namespace  vl::windows;
 5  using   namespace  vl::windows::placement;
 6 
 7  class  MainForm :  public  VL_WinForm
 8  {
 9  protected :
10      VL_WinEdit *             edtCommandLines;
11 
12       void  InitControls()
13      {
14          edtCommandLines = new  VL_WinEdit( this , true );
15          edtCommandLines -> SetVScroll( true );
16          edtCommandLines -> SetHScroll( true );
17 
18          ApplyPlacement(
19              pControl(edtCommandLines, 10 )
20              );
21 
22           this -> OnShow.Bind( this , & MainForm::MainForm_OnShow);
23      }
24 
25       void  MainForm_OnShow(VL_Base *  Sender)
26      {
27          VL_WinParameters *  Parameters = GetApplication() -> GetParameters();
28          Parameters -> Parse(L ' / ' ,L ' : ' );
29          VUnicodeString Output;
30 
31          Output += L " Command   : [ " + Parameters -> GetCommandLineString() + L " ]\r\n " ;
32           for (VInt i = 0 ;i < Parameters -> GetCount();i ++ )
33          {
34              Output += L " Parameter : [ " + Parameters -> GetParameter(i) + L " ]\r\n " ;
35              Output += L " Value     : [ " + Parameters -> GetValue(i) + L " ]\r\n " ;
36          }
37          edtCommandLines -> SetText(Output);
38      }
39 
40  public :
41      MainForm():VL_WinForm( true )
42      {
43          SetClientWidth( 400 );
44          SetClientHeight( 300 );
45          SetBorder(vwfbSingle);
46          SetText(L " Command Lines " );
47          InitControls();
48          MoveCenter();
49      }
50  };
51 
52  void  main()
53  {
54      ( new  MainForm) -> Show();
55      GetApplication() -> Run();
56  }

    然后是运行结果:
分解复杂的命令行参数_第1张图片

    程序中用到的VL_WinParameters类的代码如下:

    头文件:
 1           class  VL_WinParameters :  public  VL_Base
 2          {
 3           protected :
 4               class  CommandPair
 5              {
 6               public :
 7                  typedef VL_List < CommandPair ,  false >         List;
 8 
 9                  VUnicodeString        Parameter;
10                  VUnicodeString        Value;
11              };
12 
13              VUnicodeString            FString;
14              CommandPair::List        FCommands;
15              VWChar                    FParameterChar;
16              VWChar                    FValueChar;
17              VBool                    FParsed;
18           public :
19              VL_WinParameters(VUnicodeString Command);
20               ~ VL_WinParameters();
21 
22              VUnicodeString            GetCommandLineString();
23              VInt                    GetCount();
24              VUnicodeString            GetParameter(VInt Index);
25              VUnicodeString            GetValue(VInt Index);
26              VBool                    IsParsed();
27               void                     Parse(VWChar ParameterChar , VWChar ValueChar);
28          };

    实现文件:
  1          VL_WinParameters::VL_WinParameters(VUnicodeString Command)
  2          {
  3              FString = Command;
  4              FParsed = false ;
  5              FParameterChar = L ' \0 ' ;
  6              FValueChar = L ' \0 ' ;
  7          }
  8 
  9          VL_WinParameters:: ~ VL_WinParameters()
 10          {
 11          }
 12 
 13          VUnicodeString VL_WinParameters::GetCommandLineString()
 14          {
 15               return  FString;
 16          }
 17 
 18          VInt VL_WinParameters::GetCount()
 19          {
 20               return  FCommands.GetCount();
 21          }
 22 
 23          VUnicodeString VL_WinParameters::GetParameter(VInt Index)
 24          {
 25               return  FCommands[Index].Parameter;
 26          }
 27 
 28          VUnicodeString VL_WinParameters::GetValue(VInt Index)
 29          {
 30               return  FCommands[Index].Value;
 31          }
 32 
 33          VBool VL_WinParameters::IsParsed()
 34          {
 35               return  FParsed;
 36          }
 37 
 38           void  VL_WinParameters::Parse(VWChar ParameterChar , VWChar ValueChar)
 39          {
 40               if ( ! ParameterChar  ||   ! ValueChar) return ;
 41               if (FParameterChar != ParameterChar  ||  FValueChar != ValueChar)
 42              {
 43                  FParameterChar = ParameterChar;
 44                  FValueChar = ValueChar;
 45 
 46                  FCommands.Clear();
 47                  VL_List < VUnicodeString ,  false >  CommandStrings;
 48                  {
 49                      PCWChar Buffer = FString.Buffer();
 50                      VUnicodeString CurrentCommand;
 51                      VBool InString = false ;
 52 
 53                       while ( true )
 54                      {
 55                           if (InString)
 56                          {
 57                               switch ( * Buffer)
 58                              {
 59                               case  L ' \0 ' :
 60                                  InString = false ;
 61                                   if (CurrentCommand != L "" )
 62                                  {
 63                                      CommandStrings.Add(CurrentCommand);
 64                                      CurrentCommand = L "" ;
 65                                  }
 66                                   break ;
 67                               case  L ' \" ' :
 68                                  InString = false ;
 69                               default :
 70                                  CurrentCommand +=* Buffer;
 71                              }
 72                          }
 73                           else
 74                          {
 75                               switch ( * Buffer)
 76                              {
 77                               case  L '   ' : case  L ' \0 ' :
 78                                   if (CurrentCommand != L "" )
 79                                  {
 80                                      CommandStrings.Add(CurrentCommand);
 81                                      CurrentCommand = L "" ;
 82                                  }
 83                                   break ;
 84                               case  L ' \" ' :
 85                                  InString = true ;
 86                               default :
 87                                  CurrentCommand +=* Buffer;
 88                              }
 89                          }
 90                           if ( * Buffer)
 91                          {
 92                              Buffer ++ ;
 93                          }
 94                           else
 95                          {
 96                               break ;
 97                          }
 98                      }
 99                  }
100                   for (VInt i = 0 ;i < CommandStrings.GetCount();i ++ )
101                  {
102                      CommandPair Pair;
103                      PCWChar Buffer = CommandStrings[i].Buffer();
104                       if ( * Buffer == FParameterChar)
105                      {
106                          Buffer ++ ;
107                           while ( true )
108                          {
109                               if ( * Buffer)
110                              {
111                                   if ( * Buffer == FValueChar)
112                                  {
113                                      Buffer ++ ;
114                                       break ;
115                                  }
116                                   else
117                                  {
118                                      Pair.Parameter +=* Buffer;
119                                      Buffer ++ ;
120                                  }
121                              }
122                               else
123                              {
124                                   break ;
125                              }
126                          }
127                      }
128                       if ( * Buffer)
129                      {
130                          Pair.Value = Buffer;
131                           if (Pair.Value.Length() >= 2   &&  Pair.Value.GetChar( 0 ) == L ' \" '   &&  Pair.Value.GetChar(Pair.Value.Length() - 1 ) == L ' \" ' )
132                          {
133                              Pair.Value = Pair.Value.SubString( 1 ,Pair.Value.Length() - 2 );
134                          }
135                      }
136                      FCommands.Add(Pair);
137                  }
138                  FParsed = true ;
139              }
140          }

你可能感兴趣的:(分解复杂的命令行参数)