0

私のJavaは非常に錆びており、LinusかWin32かに応じて、シェルスクリプトまたはバッチファイルの実行を簡素化するユーザーインターフェイスを作成しようとして立ち往生しています。ファイルには、次の命名規則があります。

  module-verb-object-etc [args-list]
  mysql-connect-grid
  mysql-connect-rds
  mysql-dump-grid
  mysql-dump-grid-se314

最終的には、明確な用語を解析して、次のことができるようにしたいと思います。

  1. コマンドをトークン化し(たとえば、「-」で区切る)、foxproのコマンドウィンドウやciscoのIOSなどの簡略化された用語に短縮します(たとえば、「my cogr」はunixでは「mysql-connect-grid」を実行し、win32では* .cmdを実行します)
  2. また、IOSのスタイルでは、ユーザーが省略形のコマンドを入力できるようにして、疑問符(?)を入力できるようにします。これにより、残りの(または次の)固有のコマンドオプション(「my?」など)に関するヒントが得られます。 mysqlを返し、「my?」は接続またはダンプを返します)。その他の戻り値は、一意でないコマンドまたは一致しなかったコマンドの場合、「あいまい」または「不明」になります。些細なことのように思えるかもしれませんが、各フォルダーには何百ものコマンドがあり、ユーザーは考えたくありません...

ディレクトリからファイルのリストを取得し、ファイルの配列を再調整する関数を作成しました。次に、動的にサイズ設定された潜在的なコマンドのグリッドを返す以下の方法を使用して、それを2次元配列に変換します。

    /**********************************************************************************
     *  MAKE GRID: Parses array of filenames and tokenizes AWS cmds.
     * @param strs  Array of filenames
     **********************************************************************************/
     public static String [][] makeGrid(String strs[], boolean bPrint) {
       String tmpGrid[][];
       int nMaxCols = 0;
       int nRows = uniqueCount(strs);
       int nGridRow = 0; 
       tmpGrid = new String [nRows][]; 
       for (int nRow=0; nRow<nRows; nRow++) { 
 String cFilename = strs[nRow];
                if (!cFilename.endsWith(".cmd") // just list unix files (filter for batch files)
    && cFilename.indexOf("-") > 0 ) // make sure there's a dash in the filename
    {
           String strTokens[] = tokenize(strs[nRow], "-"); // the dash is our token deliminator
           int nCols = strTokens.length; 
           if (nCols>nMaxCols) nMaxCols=nCols;
           tmpGrid[nGridRow] = new String [nCols];
           for (int nCol=0; nCol<nCols; nCol++) { 
               tmpGrid[nGridRow][nCol] = strTokens[nCol];
               if (bPrint) System.out.print(" "+tmpGrid[nGridRow][nCol]);
             }
            nGridRow++;
            if (bPrint) System.out.println("");
     } //end-if
         }
       String[][] cmdGrid = new String[nGridRow][nMaxCols];
       System.arraycopy(tmpGrid, 0, cmdGrid, 0, nGridRow); // removes null rows  (&NPEs!)
       return cmdGrid;
      }

これは2次元配列(下)を返すのでgrid[Row-N][Col-0]、一致します。row[0]ワイルドカードcmdToken[0] && row[1]が「like」である個別の値のみをプルcmdToken[1]して、ユーザーがコマンドを"my du gr ?"返すまでコマンドをつなぎ合わせることができるようにしたいのですが"ENTER, [se314]"、それが理にかなっている場合は...

String[][] makeGrid:
    mysql dump grid se314
    mysql connect grid
    mysql dump grid
    mysql connect rds

私の課題:Javaのマッチャー関数に頭を悩ませているようには見えません。SQLの場合、次のようになります。

"SELECT DISTINCT col2 FROM cmd_Grid
   WHERE col1 LIKE 'cmdToken1%' " 

またはさらに良い:連続する各列にint深度マークを再帰的に設定する

`SELECT DISTINCT col+str(depthmark+1) FROM cmd_Grid 
    WHERE col+str(depthmark) LIKE 'cmdMatchedTokens%' " 

完全に一致するまで。

必死になって試したjoSQLというパッケージを見つけましたが、Java6で動作させることができないようです。とにかく:私はまた、すべてが単一のクラスに含まれることができるように、純粋なJavaソリューションを望んでいました...

多分スキャナーか何かを使って多次元配列を解析して一意の値を探します...私はおそらくそれを必要以上に複雑にしていることを知っています。

正しい方向にゆっくりと微調整していただければ幸いです。

TIA

4

3 に答える 3

1

また、配列の代わりにArrayListなどのより高度なデータ構造を使用し、StringTokenizerを使用して各コマンドPartをオンザフライで生成することも検討できます。

次のようになります。

ArrayList<String> matchingCommands = new ArrayList<String>();

    ArrayList<String> commandList = new ArrayList<String>();
    commandList.add("mysql dump grid se314");
    commandList.add("mysql connect grid");
    commandList.add("mysql dump grid");
    commandList.add("mysql connect rds");

    String queryCommand = "my du gr ?";

    for(int i=0; i<commandList.size(); i++)
    {
        boolean matches = false;
        String command = commandList.get(i);
        StringTokenizer commandTokenizer = new StringTokenizer(command, " "); // Using space as the deliminator
        StringTokenizer queryTokenizer = new StringTokenizer(queryCommand, " "); // Using space as the deliminator

        while(commandTokenizer.hasMoreTokens())
        {
            String queryPart = queryTokenizer.nextToken();
            String commandPart = commandTokenizer.nextToken();
            if(commandPart.startsWith(queryPart) || queryPart.equals("?")){
                matches = true;
            }else{
                matches = false;
                break;
            }
        }
        if(matches){
            matchingCommands.add(command);
        }
    }
    System.out.println(matchingCommands);

これにより、プログラムを動的に拡張でき、nullオブジェクトによるメモリの浪費もなくなります。

于 2010-01-19T17:47:13.403 に答える
0

徹底的な解決策の1つは、キーが「my co gr」のような可能な短いコマンドであり、対応する値が「mysql-connect-grid」であるようにハッシュマップを構築することです。したがって、ハッシュマップには「値としてmysql-connect-grid"。

ただし、これは、可能なキーの数が限られている場合にのみ実行可能なソリューションです。そうでない場合は、組み込みの文字列解析メソッドを使用できます。

例えば:

    String[][] makeGrid = new String[][]{{"mysql", "dump", "grid", "se314"}, 
              {"mysql", "connect", "grid", ""},
              {"mysql",  "dump", "grid", ""},
              {"mysql", "connect", "rds", ""}
              };
     String[] query2 = new String[]{"my", "du", "gr"};

  String[][] matchingCommands = new String[4][4];
  int resultSize = 0;
     for(int i=0; i<makeGrid.length; i++)
  {
      String[] commandColumn = makeGrid[i];
   boolean matches = false;
      for(int cnt=0; cnt<commandColumn.length; cnt++)
      {
       String commandPart = commandColumn[cnt];
       if(cnt < query2.length){
        String queryPart = query2[cnt];
     if(commandPart.startsWith(queryPart) || queryPart.equals("?")){
         matches = true;
        }else{
         matches = false;
         break;
        }
       }
      }
      if(matches){
       matchingCommands[resultSize] = commandColumn;
       resultSize++;
      }
  }

このコードスニペットは、それを実行する方法についてのアイデアを提供するはずです。ただし、ここで注意すべきことが1つあります。matchingCommands配列は、4行4列に初期化されていますが、一致がそれより少なくなるため、無駄になります。これをより効率的にするためにサポートが必要な場合はお知らせください。そうでなければ、これは私があなたが望むことをするだろうと思うコードの実用的な部分です。

于 2010-01-19T01:10:45.053 に答える
0

今、私は空白の区切り文字の各cmdString(クエリ)を解析し、配列をトークン化することをいじっていました。何かのようなもの:

 Scanner sCmdString = new Scanner(cInput);
 while (sCmdString.hasNext()) { 
 String cToken = sCmdString.next().toUpperCase().trim();
 System.out.println(" "+cToken+" ");
 // match cmdString[i..n] to cmdGrid
 for (int nRow=0; nRow < cmdGrid.length; nRow++) {
       for (int nCol=0; nCol < cmdGrid[nRow].length; nCol++) {
  if (cmdGrid[nRow][nCol].equalsIgnoreCase(cToken) )
     System.out.println("MATCH: "+cmdGrid[nRow][nCol]);
  else System.out.println("NO MATCH:"+cmdGrid[nRow][nCol].toUpperCase()+":"+cToken+"...");
        }
   }
   }

しかし、行の長さが不均一なNPEを取得していました。

そして、私は柱を平らにするというあなたの考えが好きです。

私はまだ重複を削除する必要があると思います...いいえ?

于 2010-01-19T02:13:03.817 に答える