Java シェル ワイルドカード トークナイザー
-
21-09-2019 - |
質問
私の Java は非常に錆びており、Linus か Win32 かに応じてシェル スクリプトまたはバッチ ファイルの実行を簡素化するユーザー インターフェイスを作成しようとして立ち往生しています。ファイルには次の命名規則があります。
module-verb-object-etc [args-list]
mysql-connect-grid
mysql-connect-rds
mysql-dump-grid
mysql-dump-grid-se314
最終的には、明確な用語を解析して次のことができるようにしたいと考えています。
- コマンドをトークン化し(例:「-」で区切る)、foxpro のコマンド ウィンドウや cisco の IOS のような簡略化した用語に短縮します(例:「my co gr」は、UNIX では「mysql-connect-grid」を実行し、win32 では *.cmd を実行します)
- また、IOS のスタイルでは、ユーザーが疑問符 (?) を入力できるように短縮コマンドを入力でき、残りの (または次の) 固有のコマンド オプションに関するヒントが表示されます (例:"私の?" 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]
のようなものです" 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 では動作しないようです。ともかく:また、すべてを 1 つのクラスに含めることができる純粋な Java ソリューションも望んでいました...
おそらくスキャナか何かを使用して、多次元配列を解析して一意の値を取得するのでしょう...おそらく必要以上に複雑にしてしまっているのはわかっています。
正しい方向に優しく押していただければ幸いです。
TIA
解決
一つの徹底的な解決策は、キーが「私の共同のGR 『のmysql-接続グリッド」と対応する値がある』などの可能短いコマンドであるように、HashMapをcontructする可能性があります。 だから、値として「mysqlのコネクト・グリッド」を持つことになりますハッシュマップの値が存在することになる。
しかし、これは可能なキーの有限数がある場合にのみ実行可能なソリューションです。 それはケースではありません場合は、文字列の解析方法に建てられています。
を使用することができます 例えば、
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列に初期化されています。あなたは、これがより効率的に助けが必要なら、私に教えてください。そうでなければ、これは私が思うのコードの作業部分は何をしたいんです。
他のヒント
また、配列の代わりに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);
これはあなたのプログラムが動的に拡張できることを確認してしまうとメモリのない浪費が原因ヌルではありませんいずれかのオブジェクトます。
今の私は、ホワイトスペース区切り文字のために、各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を得ていました。
とI列を平坦化するアイデアのように。
私はまだ重複を削除する必要があると思う...ない?