2

次のようなコマンドを解析するには、正規表現が必要です。

C:\Program Files\Internet Explorer\iexplore.exe https:\www.google.com
C:\Program Files\Internet Explorer\iexplore.exe http:\www.google.com
C:\Program Files\Internet Explorer\iexplore .exe www.google.com
iexplore.exe https:\www.google.com
コピー C:\test.txt D:\

ポイントは、最初の部分をコマンドとして取得し、他の部分を引数として取得したいということです。コマンドは、、などを含む何でもかまい.batません.vbs.exe

コマンドにスペースがなければ正常に機能する正規表現を見つけました。

string str = @"C:\xcopy D:\test.txt D:\Test";

string pattern = @"^(?:""([^""]*)""\s*|([^""\s]+)\s*)+";        
Regex parseDir = new Regex(pattern, RegexOptions.IgnoreCase);
if(parseDir.IsMatch(str))
{
    Match dir = parseDir.Match(str);
    var captures = dir.Groups[1].Captures.Cast<Capture>().Concat(
       dir.Groups[2].Captures.Cast<Capture>()).
       OrderBy(x => x.Index).
       ToArray();
    string cmd = captures[0].Value;
    string arguments = string.Empty;
    for (int i = 1; i < captures.Length; i++)
    {
        arguments += captures[i].Value + " ";    
    }
    Console.WriteLine(cmd);
    Console.WriteLine(arguments);
}
4

3 に答える 3

1

あなたの質問から、私はあなたがWindowsOSでテキストでバッチコマンドを渡す方法を探していると思います。これを正常に行うために私が考えることができる唯一の方法は、すべてのコマンドのリストがある場合、またはプログラムがシステム内のすべての.exeファイルを抽出できる場合、最初のexeファイルがどこにあるかを正常に確認できることです。コマンドのターゲットプログラムはであり、他のプログラムを引数として想定します。

このようにして、次のように抽出を行うことができます(非正規表現メソッド):

var cmd = "copy this.txt C:\t.txt"
var program = getTargetProgram(cmd);
var args = cmd.Substring(cmd.IndexOf(program) + program.length).trim().split(' ');

あなたgetTargetProgram()はこのように行くことができます:

private string getTargetProgram(string cmd)
{
    //first test if it's a normal executable
    if(File.Exists(cmd.Substring(0, cmd.IndexOf(".exe") + 4)) //return this extract;
    foreach(string s in winProgramList)
    {
       if(cmd.StartsWith(s)){
             //voila, we can return the target
       }
    }
}
于 2012-11-04T16:29:44.330 に答える
1

標準のコンソールアプリケーションを使用している場合、メインのエントリポイントargs[]はすでにこれを解析しています。ここに注意点があります。これは、提供した例がスペース(C:\ Program Files)のために機能しないためですが、引用符で囲むと( "C:\ Program Files \ Internet ... \ iexplorer .exe ")これは正しく機能することがわかります。

このリンクでは、コンソールアプリケーションの作成について説明します

アップデート:

それでは、コンソールアプリケーションではないが、コンソールアプリケーションの起動ルーチンが提供するものを正確にシミュレートしたい場合は、唯一のCommandLineToArgvWネイティブメソッドを紹介します。

    [DllImport("shell32.dll", SetLastError = true)]
    static extern IntPtr CommandLineToArgvW(
        [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, 
        out int pNumArgs);

このばかばかしいほど単純なメソッドは、任意の文字列を受け取り、それを配列に変換します。これは、テキスト入力を整形式の配列に変換するために使用できるユーティリティクラスです。

    /// <summary>
/// Wrapper class for Win32 API calls
/// </summary>
public class NativeMethods
{

    [DllImport("shell32.dll", SetLastError = true)]
    static extern IntPtr CommandLineToArgvW(
        [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs);

    /// <summary>
    /// Parse a string into an array, including items in quotes
    /// </summary>
    /// <param name="commandLine"></param>
    /// <returns></returns>
    public static string[] CommandLineToArgs(string commandLine)
    {
        if (String.IsNullOrEmpty(commandLine))
            return new string[] {};

        int argc;
        var argv = CommandLineToArgvW(commandLine, out argc);
        if (argv == IntPtr.Zero)
            throw new System.ComponentModel.Win32Exception();
        try
        {
            var args = new string[argc];
            for (var i = 0; i < args.Length; i++)
            {
                var p = Marshal.ReadIntPtr(argv, i * IntPtr.Size);
                args[i] = Marshal.PtrToStringUni(p);
            }

            return args;
        }
        finally
        {
            Marshal.FreeHGlobal(argv);
        }
    }
}
于 2012-11-04T16:19:06.783 に答える
0

プログラムのパス/名前(スペースが含まれている場合)を引用符で囲むか、プログラムの一部を理解するために追加のコードを記述する必要があります。

頭に浮かぶアプローチの1つは、最初のキャプチャから開始し(iexplorer.exeたとえば、C:\Program)、それが有効なプログラムであるかどうかを確認することです。そうでない場合は、スペースを使用して次のキャプチャを追加し(たとえば、C:\Program+ Files\Internet=> C:\Program Files\Internet)、チェックを繰り返します。キャプチャがなくなるか、有効なプログラムが見つかるまで繰り返し、残りは通常どおり引数として扱います。

別の回答が示唆しているように、手動で解析を行う理由はありません。正規表現は引き続き機能します。

于 2012-11-04T17:00:38.093 に答える