Pregunta

Mi Java es muy oxidada y estoy atascado tratando de hacer una interfaz de usuario que simplifica la ejecución de secuencias de comandos shell o archivos por lotes dependiendo de si se trata de Linus o Win32 respectivamente. Los archivos tienen la siguiente convención de nombres.

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

última instancia, me gustaría analizar manera inequívoca para que pueda:

  1. tokenize los comandos (por ejemplo, delimitados por "-") y les acorta en términos simplificados soemthing como ventana de comandos de FoxPro o IOS de Cisco (por ejemplo, "mi co gr" ejecuta "mysql-connect-grid" en UNIX y * .cmd en Win32)
  2. y también en el estilo de IOS permite al usuario introducir comandos abreviados para que puedan escribir en un signo de interrogación (?) Y se les dará una pista sobre el único restante (o siguiente) opciones de comando (por ejemplo " mi?" vuelve mysql & '' devuelve mis? conectan, o volcado). valores de retorno othr serían "ambigua" o "desconocido" para los comandos que no son únicos o no podría ser igualada. Puede parecer trivial, pero hay muchos cientos de comandos en cada carpeta y mis usuarios no quiero pensar ...

escribí una función para tirar de la lista de archivos de un directorio y retun una serie de fileanmes. Entonces convierto que en una matriz de 2 dimensiones usando el método siguiente que devuelve un tamaño de rejilla dynamicly de comandos posibles.

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

Esto devuelve una matriz 2-D (a continuación), por lo grid[Row-N][Col-0] es un partido. Me gustaría tirar sólo valores únicos donde row[0] es un partido de comodín para cmdToken[0] && row[1] es "como" cmdToken[1] para que mis usuarios pueden armar un comando hasta que vuelve "my du gr ?" "ENTER, [se314]" - si eso tiene sentido ...

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

Mi Reto: Parece que no puedo conseguir mi cabeza alrededor de mi función de coincidencias en Java. Si se trataba de SQL sería algo como:

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

o incluso mejor: el establecimiento de una forma recursiva depthmark int para cada columna consecutiva

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

hasta que haya una coincidencia exacta.

He encontrado un paquete llamado joSQL que probé por desesperación pero parece que no puede conseguir que funcione en java6. De todos modos: Yo también estaba esperando una solución pura de Java para que todo pudiera estar contenido en una sola clase ...

Tal vez utilizando el escáner o algo para analizar mi matriz multidimensional de valores únicos ... Sé que probablemente lo estoy haciendo de manera más compleja de lo que debe ser.

un empujoncito suave en la dirección correcta sería apreciada.

TIA

¿Fue útil?

Solución

Una solución exhaustiva podría ser así construir un HashMap por lo que la clave es un posible comando corto, como 'mi co gr" y el valor correspondiente es 'mysql-conectan de la red'. Lo que no habría valores en el mapa hash que tendrá "mysql de conexión de la red" como valor.

Sin embargo, esta es una solución viable sólo si hay un número finito de posibles claves. Si ese no es el caso, entonces usted puede utilizar el construido en la cadena de métodos de análisis.

Por ejemplo:

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

Este fragmento de código debe darle una idea de cómo hacerlo. Hay una cosa que tener en cuenta aquí, sin embargo. La matchingCommands array se ha inicializado a las 4 filas y 4 columnas, que es un desperdicio porque los partidos será menor que eso. Déjeme saber si usted necesita ayuda para hacer esto más eficiente. De lo contrario, se trata de una pieza de trabajo de código que creo que hace lo que quiere.

Otros consejos

También se puede ver en el uso algunas estructuras de datos más avanzadas como un ArrayList en lugar de una matriz y utilizando la StringTokenizer para generar cada comando Parte sobre la marcha.

Será algo como esto:

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

Esto se aseguraría de que su programa puede crecer de forma dinámica y no hay desperdicio de memoria debido a objetos nulos tampoco.

ahora yo estaba jugando un poco con el análisis cada cmdstring (consulta) para los delimitadores de espacio en blanco y tokenizar la matriz. Algo así como:

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

pero me estaba NPE con las longitudes de filas irregulares.

Y me gusta su idea de aplanamiento de las columnas.

Creo que todavía tendría que eliminar duplicados ... no?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top