Java Shell 通配符标记生成器

发布于 2024-08-18 11:25:47 字数 3151 浏览 3 评论 0原文

我的 Java 非常生疏,我一直在尝试制作一个用户界面来简化 shell 脚本或批处理文件的执行,具体取决于它是 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 co gr”在unix中执行“mysql-connect-grid”,在win32中执行*.cmd),
  2. 并且以IOS的风格允许用户输入缩写命令,以便他们可以输入问号(?),它会给他们一个关于唯一的剩余(或下一个)命令选项的提示(例如“my?”返回 mysql &“my ?”返回 connect 或 dump )。对于不唯一或无法匹配的命令,其他返回值将是“不明确的”或“未知的”。这可能看起来微不足道,但每个文件夹中有数百个命令,我的用户不想去想...

我编写了一个函数来从目录中提取文件列表&重新调整 fileanmes 数组。然后,我使用下面的方法将其转换为二维数组,该方法返回动态大小的潜在命令网格。

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

这将返回一个二维数组(如下),因此 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 中的匹配器函数。如果是 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

My Java is extremely rusty and I'm stuck trying to make a user interface that simplifies the execution of shell scripts or batch files depending on whether it's Linus or Win32 respectively. The files have the following naming convention.

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

ultimately I would like it to parse unambiguous terms so I can:

  1. tokenize the commands (e.g delimited by "-") & shorten them into simplified terms soemthing like foxpro's command window or cisco's IOS (eg "my co gr" executes "mysql-connect-grid" in unix and *.cmd in win32)
  2. and also in the style of IOS allow the user to enter abbreviated commands so that they can type in a question mark (?) and it will give them a hint as to the unique remaining (or next) command options (e.g. "my?" returns mysql & "my ?" returns connect, or dump). Othr return values would be "ambiguous" or "unknown" for commands that are not unique or could not be matched. It may seem trivial but there are many hundreds of commands in each folder and my users don't want to think...

I wrote a function to pull the list of files from a directory & retun an array of fileanmes. Then I convert that into a 2 dimensional array using the method below which returns a dynamicly sized grid of potential commands.

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

This returns a 2-d array (below), so grid[Row-N][Col-0] is a match. I'd like to pull only distinct values where row[0] is a wildcard match for cmdToken[0] && row[1] is "like" cmdToken[1] so that my users can piece together a command until "my du gr ?" returns "ENTER, [se314]" - if that makes sense...

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

My Challenge: I cant seem to get my head around my matcher function in java. If it was SQL it would be something like:

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

or even better: recursively setting a int depthmark for each consecutive column

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

until you have an exact match.

I found a package called joSQL that I tried out of desperation but I cant seem to get it to work in Java6. Anyway: I was also hoping for a pure java solution so that everything could be contained in a single class...

Maybe using scanner or something to parse my multidimentional array for unique values... I know I'm probably making it way more complex than it needs to be.

a gentle nudge in the right direction would be appreciated.

TIA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

累赘 2024-08-25 11:25:47

您还可以考虑使用一些更高级的数据结构,例如 ArrayList 而不是数组,并使用 StringTokenizer 动态生成每个命令部分。

它将是这样的:

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

这将确保您的程序可以动态增长,并且也不会因为空对象而浪费内存。

You could also look into using some more advanced data structures like an ArrayList instead of an array and using the StringTokenizer to generate each command Part on the fly.

It will be something like this:

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

This would make sure that your program can grow dynamically and there is no wastage of memory because of null objects either.

岁吢 2024-08-25 11:25:47

一种详尽的解决方案可能是构造一个 hashMap,以便键是可能的短命令,例如“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++;
      }
  }

此代码片段应该让您了解如何进行操作。不过这里有一点需要注意。 ma​​tchingCommands 数组已初始化为 4 行和 4 列,这是浪费的,因为匹配项将少于此值。如果您需要帮助提高效率,请告诉我。否则,这是一段工作代码,我认为它可以满足您的需求。

One exhaustive solution could be to contruct a hashMap so that the key is a possible short command like 'my co gr" and the corresponding value is "mysql-connect-grid".
So there would be values in the hash map that will have "mysql-connect-grid" as the value.

But this is a feasible solution only if there is a finite number of possible keys.
If that's not the case, then you can use the built in string parsing methods.

For example:

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

This code snippet should give you some idea of how to go about it. There is one thing to note here though. The matchingCommands array has been initialized to the 4 rows and 4 columns which is wasteful because the matches will be lesser than that. Let me know if you need help making this more efficient. Otherwise, this is a working piece of code which I think does what you want.

复古式 2024-08-25 11:25:47

现在我正在尝试解析每个 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 行长度不均匀。

我喜欢你把列展平的想法。

我想我仍然需要删除重复项...不是吗?

right now I was toying around with parsing each cmdString (query) for white-space delimiters & tokenizing the array. Something like:

 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+"...");
        }
   }
   }

but I was getting NPEs with the uneven row lengths.

AND I like your idea of flattening out the columns.

I think I'd still have to remove duplicates... no?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文