2010-01-19 15 views
0

我的Java非常生疏,我試圖製作一個簡化shell腳本或批處理文件執行的用戶界面,這取決於它是分別是Linus還是Win32。這些文件具有以下命名約定。Java Shell通配符分詞器

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

最終我想它解析毫不含糊所以可以:

  1. 記號化的命令(例如,由分隔「 - 」)&縮短它們變成簡化術語soemthing像FoxPro的命令窗口或Cisco的IOS(例如,「我的公司」在unix中執行「mysql-connect-grid」和在win32中執行* .cmd)
  2. 並且還以IOS的風格允許用戶輸入縮寫命令,以便他們可以鍵入問題標記(?),它會給他們提示唯一的剩餘(或下一個)命令選項(例如「我的?「返回mysql &」my?「返回連接或轉儲)。對於不唯一或無法匹配的命令,Othr返回值將是「模糊的」或「未知的」。它可能看起來微不足道,但也有數百個命令中的每個文件夾中,我的用戶不想去思考...

我寫了一個函數來拉從一個目錄中的文件列表& retun數組fileanmes。然後,我使用下面的方法將其轉換爲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-d陣列(下面),因此grid[Row-N][Col-0]匹配。我想拉只不同的值,其中row[0]cmdToken[0] && row[1]通配符匹配「像」 cmdToken[1]讓我的用戶可以到"my du gr ?"回報"ENTER, [se314]"拼湊出一個命令 - 如果是有道理的......

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

我的挑戰:我似乎無法在java中使用我的matcher函數。如果它是SQL它會是這樣的:

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

甚至更​​好:遞歸設置INT depthmark每次連續列

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

,直到你完全匹配。

我發現了一個名爲joSQL的包,我嘗試了絕望,但似乎無法讓它在Java6中工作。無論如何:我也希望有一個純粹的Java解決方案,以便一切都可以包含在一個類...

也許使用掃描儀或東西來解析我的multidimentional數組的唯一值...我知道我可能使它比它需要的更復雜。

在正確的方向溫和微調將不勝感激。

TIA

+0

我不知道爲什麼它殺死了該方法的代碼......但是,我想這並不重要。我還沒有完全搞清楚下一部分,但可能傳遞給一個java.lang.ProcessBuilder函數來執行另一個獨立的Java程序或腳本或批處理文件 - 根據操作系統 – WWWIZARDS 2010-01-19 00:36:47

回答

0

一個詳盡的解決辦法是去構造一個HashMap所以,關鍵是像「我的合作GR可能簡短的命令」和相應的價值‘的mysql-連接網’。 所以就是哈希映射中值爲「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++; 
     } 
    } 

這段代碼應該給你如何去它的一些想法。這裏有一點需要注意。 matchingCommands數組已被初始化爲4行和4列,這是浪費的,因爲匹配會比這少。讓我知道你是否需要幫助使這種效率更高。否則,這是一段代碼,我認爲這是你想要的。

+0

非常有趣...感謝您的快速回復。我嘗試了一個哈希映射,但它的方式太毛茸茸了。我不記得確切的細節,但我認爲我有一個相當於重複鍵的問題。我也放棄了動態數組維度的B/C .. 基本上,cmdGrid行可以有任意數量的列 - 但你給了我一個想法用空字符串填充空元素「」不是最優雅的,但它可以工作。 – WWWIZARDS 2010-01-19 02:11:41

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的行長不均勻。

而且我喜歡將平面展平的想法。

我想我仍然必須刪除重複...不是?

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

這將確保您的程序可以動態地增長並沒有因爲空對象的內存或者浪費。