分割字符串包含的命令行参数转换成在C#字符串[]分割字符串包含的命令行参数转换成在C#字符串[](S

2019-05-10 11:47发布

我有一个包含要被传递到另一个可执行命令行参数的单个串和我需要提取包含C#会如果已在命令行中指定的命令以同样的方式的各个参数的字符串[]。 字符串[]将执行经由反射另一组件的入口点时使用。

对此有一个标准的功能? 或者是有用于正确分割参数的优选方法(正则表达式?)? 它必须处理'“,可能包含正确的空格分隔字符串,所以我不能随便拆的‘’。

例如字符串:

string parameterString = @"/src:""C:\tmp\Some Folder\Sub Folder"" /users:""abcdefg@hijkl.com"" tasks:""SomeTask,Some Other Task"" -someParam foo";

实施例的结果:

string[] parameterArray = new string[] { 
  @"/src:C:\tmp\Some Folder\Sub Folder",
  @"/users:abcdefg@hijkl.com",
  @"tasks:SomeTask,Some Other Task",
  @"-someParam",
  @"foo"
};

我并不需要一个命令行解析库,只是一种方式来获得应产生的String []。

更新 :我不得不改变预期的结果匹配什么是C#实际产生(在分割字符串去除多余“的)

Answer 1:

除了善良纯洁的托管解决方案由埃里克 ,它可能是值得一提的,为了完整起见,该Windows还提供了CommandLineToArgvW分手字符串转换成字符串数组功能:

 LPWSTR *CommandLineToArgvW( LPCWSTR lpCmdLine, int *pNumArgs); 

解析一个Unicode命令行串,并返回一个指针数组,以命令行参数,利用这样的参数的计数沿,在某种程度上是类似于标准C运行时的argv和argc个值。

调用从C#这个API和拆包在托管代码生成的字符串阵列的例子可以在以下网址找到:“ 转换命令行字符串使用CommandLineToArgvW()API参数数量[] ”。下面是相同的代码的一个稍微简单的版本:

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

public static string[] CommandLineToArgs(string commandLine)
{
    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);
    }
}


Answer 2:

这惹恼了我,有没有功能拆分根据检查每个字符函数的字符串。 如果有,你可以写这样的:

    public static IEnumerable<string> SplitCommandLine(string commandLine)
    {
        bool inQuotes = false;

        return commandLine.Split(c =>
                                 {
                                     if (c == '\"')
                                         inQuotes = !inQuotes;

                                     return !inQuotes && c == ' ';
                                 })
                          .Select(arg => arg.Trim().TrimMatchingQuotes('\"'))
                          .Where(arg => !string.IsNullOrEmpty(arg));
    }

尽管已经写了,为什么不写了必要的扩展方法。 好吧,你说服我吧...

首先,我自己斯普利特版本,需要有决定指定字符是否应该拆分字符串的函数:

    public static IEnumerable<string> Split(this string str, 
                                            Func<char, bool> controller)
    {
        int nextPiece = 0;

        for (int c = 0; c < str.Length; c++)
        {
            if (controller(str[c]))
            {
                yield return str.Substring(nextPiece, c - nextPiece);
                nextPiece = c + 1;
            }
        }

        yield return str.Substring(nextPiece);
    }

这可能会产生一些空字符串视情况而定,但也许这些信息将会在其他情况下是有用的,所以我没有在这个函数删除空项。

其次(更世俗的)一个小帮手,将修剪匹配对从字符串的开始和结束的报价。 它比标准的修剪方法更加挑剔 - 它只会从两端修剪一个字符,它不会只从一个端部修整:

    public static string TrimMatchingQuotes(this string input, char quote)
    {
        if ((input.Length >= 2) && 
            (input[0] == quote) && (input[input.Length - 1] == quote))
            return input.Substring(1, input.Length - 2);

        return input;
    }

我想你会想一些测试也是如此。 好吧,好吧。 但是,这必须是绝对的最后一件事! 首先一个辅助函数,与预期阵列内容的分割的结果进行比较:

    public static void Test(string cmdLine, params string[] args)
    {
        string[] split = SplitCommandLine(cmdLine).ToArray();

        Debug.Assert(split.Length == args.Length);

        for (int n = 0; n < split.Length; n++)
            Debug.Assert(split[n] == args[n]);
    }

然后,我可以写这样的测试:

        Test("");
        Test("a", "a");
        Test(" abc ", "abc");
        Test("a b ", "a", "b");
        Test("a b \"c d\"", "a", "b", "c d");

下面是测试你的要求:

        Test(@"/src:""C:\tmp\Some Folder\Sub Folder"" /users:""abcdefg@hijkl.com"" tasks:""SomeTask,Some Other Task"" -someParam",
             @"/src:""C:\tmp\Some Folder\Sub Folder""", @"/users:""abcdefg@hijkl.com""", @"tasks:""SomeTask,Some Other Task""", @"-someParam");

需要注意的是实施具有额外的功能,这将消除围绕一个参数报价如果是有道理的(感谢TrimMatchingQuotes功能)。 我认为这是正常的命令行解释的一部分。



Answer 3:

Windows命令行分析器的行为就像你说的,在空间分割,除非有前一个未关闭的报价。 我会推荐自己编写解析器。 事情是这样的,也许:

    static string[] ParseArguments(string commandLine)
    {
        char[] parmChars = commandLine.ToCharArray();
        bool inQuote = false;
        for (int index = 0; index < parmChars.Length; index++)
        {
            if (parmChars[index] == '"')
                inQuote = !inQuote;
            if (!inQuote && parmChars[index] == ' ')
                parmChars[index] = '\n';
        }
        return (new string(parmChars)).Split('\n');
    }


Answer 4:

我把从杰弗里大号Whitledge答案 ,并增强了一点。

现在,支持单,双引号。 您可以通过使用其它类型化引号使用的参数本身的报价。

它还条从参数引号,因为这些不给说法的信息作出贡献。

    public static string[] SplitArguments(string commandLine)
    {
        var parmChars = commandLine.ToCharArray();
        var inSingleQuote = false;
        var inDoubleQuote = false;
        for (var index = 0; index < parmChars.Length; index++)
        {
            if (parmChars[index] == '"' && !inSingleQuote)
            {
                inDoubleQuote = !inDoubleQuote;
                parmChars[index] = '\n';
            }
            if (parmChars[index] == '\'' && !inDoubleQuote)
            {
                inSingleQuote = !inSingleQuote;
                parmChars[index] = '\n';
            }
            if (!inSingleQuote && !inDoubleQuote && parmChars[index] == ' ')
                parmChars[index] = '\n';
        }
        return (new string(parmChars)).Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
    }


Answer 5:

本善良纯洁的托管解决方案由埃里克没能处理这样的论点:

Test("\"He whispered to her \\\"I love you\\\".\"", "He whispered to her \"I love you\".");

它返回3个要素:

"He whispered to her \"I
love
you\"."

所以在这里是为了支持“援引\”逃离\“引用”修复:

public static IEnumerable<string> SplitCommandLine(string commandLine)
{
    bool inQuotes = false;
    bool isEscaping = false;

    return commandLine.Split(c => {
        if (c == '\\' && !isEscaping) { isEscaping = true; return false; }

        if (c == '\"' && !isEscaping)
            inQuotes = !inQuotes;

        isEscaping = false;

        return !inQuotes && Char.IsWhiteSpace(c)/*c == ' '*/;
        })
        .Select(arg => arg.Trim().TrimMatchingQuotes('\"').Replace("\\\"", "\""))
        .Where(arg => !string.IsNullOrEmpty(arg));
}

测试了2个额外的情况:

Test("\"C:\\Program Files\"", "C:\\Program Files");
Test("\"He whispered to her \\\"I love you\\\".\"", "He whispered to her \"I love you\".");

还指出, 接受的答案通过与Atif阿齐兹它采用CommandLineToArgvW也失败了。 它返回4个元素:

He whispered to her \ 
I 
love 
you". 

希望这可以帮助别人寻找在未来这样的解决方案。



Answer 6:

Environment.GetCommandLineArgs()



Answer 7:

我喜欢迭代器和时下LINQ使得IEnumerable<String>为容易可用作串的阵列,所以我采取以下的精神杰弗里大号Whitledge的回答是(作为扩展方法来string ):

public static IEnumerable<string> ParseArguments(this string commandLine)
{
    if (string.IsNullOrWhiteSpace(commandLine))
        yield break;

    var sb = new StringBuilder();
    bool inQuote = false;
    foreach (char c in commandLine) {
        if (c == '"' && !inQuote) {
            inQuote = true;
            continue;
        }

        if (c != '"' && !(char.IsWhiteSpace(c) && !inQuote)) {
            sb.Append(c);
            continue;
        }

        if (sb.Length > 0) {
            var result = sb.ToString();
            sb.Clear();
            inQuote = false;
            yield return result;
        }
    }

    if (sb.Length > 0)
        yield return sb.ToString();
}


Answer 8:

这个代码项目的文章是我在过去的习惯。 它的代码的好一点,但它可能工作。

这MSDN文章是我能找到的唯一解释C#如何解析命令行参数。



Answer 9:

在你的问题,你问一个正则表达式,而我也是其中的一大风扇和用户,所以当我需要做的这个相同的参数分裂为你,我周围的Googling和没有找到一个简单的解决方案后,写我自己的正则表达式。 我喜欢短的解决方案,所以我做了一个在这里它是:

            var re = @"\G(""((""""|[^""])+)""|(\S+)) *";
            var ms = Regex.Matches(CmdLine, re);
            var list = ms.Cast<Match>()
                         .Select(m => Regex.Replace(
                             m.Groups[2].Success
                                 ? m.Groups[2].Value
                                 : m.Groups[4].Value, @"""""", @"""")).ToArray();

它处理的空白,并引述引号内,并将其转换封闭“”到”请随意使用的代码!



Answer 10:

一个纯粹的管理解决方案可能会有所帮助。 还有的WINAPI功能太多的“问题”的意见,这不是其他平台。 这里是我的代码,有一个良好定义的行为(如果你喜欢,你可以更改)。

它应该做的像什么.NET / Windows中的操作提供当string[] args参数,我已经与一些“有趣”的价值观进行了比较。

这是一个典型状态机的实现拍摄每一个单个字符从输入字符串并把它解释为当前状态,产生输出,并且一个新的状态。 的状态下在各变量定义escapeinQuotehadQuoteprevCh ,并且输出被收集在currentArgargs

有的,我已经由一个真正的命令提示符实验(Windows 7)中发现的特色: \\生产\\"生产" ""内的报价范围产生"

^字符似乎是不可思议,太:它总是在不增加一倍消失。 否则,它有一个真正的命令行没有影响。 我的实现不支持这一点,因为我还没有发现这种行为的模式。 也许有人知道更多关于它。

不属于该模式的东西是下面的命令:

cmd /c "argdump.exe "a b c""

cmd命令似乎赶上外报价和逐字采取休息。 必须有一些特殊的魔力酱在此。

我已经做了我的方法没有基准,但认为这是相当快的。 它不使用Regex ,并没有做任何的字符串连接,而是使用StringBuilder收集字符参数,并把它们放入一个列表。

/// <summary>
/// Reads command line arguments from a single string.
/// </summary>
/// <param name="argsString">The string that contains the entire command line.</param>
/// <returns>An array of the parsed arguments.</returns>
public string[] ReadArgs(string argsString)
{
    // Collects the split argument strings
    List<string> args = new List<string>();
    // Builds the current argument
    var currentArg = new StringBuilder();
    // Indicates whether the last character was a backslash escape character
    bool escape = false;
    // Indicates whether we're in a quoted range
    bool inQuote = false;
    // Indicates whether there were quotes in the current arguments
    bool hadQuote = false;
    // Remembers the previous character
    char prevCh = '\0';
    // Iterate all characters from the input string
    for (int i = 0; i < argsString.Length; i++)
    {
        char ch = argsString[i];
        if (ch == '\\' && !escape)
        {
            // Beginning of a backslash-escape sequence
            escape = true;
        }
        else if (ch == '\\' && escape)
        {
            // Double backslash, keep one
            currentArg.Append(ch);
            escape = false;
        }
        else if (ch == '"' && !escape)
        {
            // Toggle quoted range
            inQuote = !inQuote;
            hadQuote = true;
            if (inQuote && prevCh == '"')
            {
                // Doubled quote within a quoted range is like escaping
                currentArg.Append(ch);
            }
        }
        else if (ch == '"' && escape)
        {
            // Backslash-escaped quote, keep it
            currentArg.Append(ch);
            escape = false;
        }
        else if (char.IsWhiteSpace(ch) && !inQuote)
        {
            if (escape)
            {
                // Add pending escape char
                currentArg.Append('\\');
                escape = false;
            }
            // Accept empty arguments only if they are quoted
            if (currentArg.Length > 0 || hadQuote)
            {
                args.Add(currentArg.ToString());
            }
            // Reset for next argument
            currentArg.Clear();
            hadQuote = false;
        }
        else
        {
            if (escape)
            {
                // Add pending escape char
                currentArg.Append('\\');
                escape = false;
            }
            // Copy character from input, no special meaning
            currentArg.Append(ch);
        }
        prevCh = ch;
    }
    // Save last argument
    if (currentArg.Length > 0 || hadQuote)
    {
        args.Add(currentArg.ToString());
    }
    return args.ToArray();
}


Answer 11:

使用:

public static string[] SplitArguments(string args) {
    char[] parmChars = args.ToCharArray();
    bool inSingleQuote = false;
    bool inDoubleQuote = false;
    bool escaped = false;
    bool lastSplitted = false;
    bool justSplitted = false;
    bool lastQuoted = false;
    bool justQuoted = false;

    int i, j;

    for(i=0, j=0; i<parmChars.Length; i++, j++) {
        parmChars[j] = parmChars[i];

        if(!escaped) {
            if(parmChars[i] == '^') {
                escaped = true;
                j--;
            } else if(parmChars[i] == '"' && !inSingleQuote) {
                inDoubleQuote = !inDoubleQuote;
                parmChars[j] = '\n';
                justSplitted = true;
                justQuoted = true;
            } else if(parmChars[i] == '\'' && !inDoubleQuote) {
                inSingleQuote = !inSingleQuote;
                parmChars[j] = '\n';
                justSplitted = true;
                justQuoted = true;
            } else if(!inSingleQuote && !inDoubleQuote && parmChars[i] == ' ') {
                parmChars[j] = '\n';
                justSplitted = true;
            }

            if(justSplitted && lastSplitted && (!lastQuoted || !justQuoted))
                j--;

            lastSplitted = justSplitted;
            justSplitted = false;

            lastQuoted = justQuoted;
            justQuoted = false;
        } else {
            escaped = false;
        }
    }

    if(lastQuoted)
        j--;

    return (new string(parmChars, 0, j)).Split(new[] { '\n' });
}

基于蒸汽在胡同里的答案,这其中也支持^逃逸。

例子:

  • 这是一个测试
    • 这个
    • 一个
    • 测试
  • 这是一个测试
    • 这个
    • 测试
  • 这^“是一个^”测试
    • 这个
    • “是
    • 一个”
    • 测试
  • 这个“”“是^^测试”
    • 这个
    • 是^测试

它还支持多种空间(休息参数每块空间只是一个时间)。



Answer 12:

哦赫克。 这一切都... Eugh。 但是,这是合法的官员。 从微软的C#.NET为核心,也许仅适用于Windows,也许是跨平台的,但麻省理工学院的许可。

选择花絮,方法的声明和显着的意见;

internal static unsafe string[] InternalCreateCommandLine(bool includeArg0)
private static unsafe int SegmentCommandLine(char * pCmdLine, string[] argArray, bool includeArg0)
private static unsafe int ScanArgument0(ref char* psrc, char[] arg)
private static unsafe int ScanArgument(ref char* psrc, ref bool inquote, char[] arg)

-

// First, parse the program name (argv[0]). Argv[0] is parsed under special rules. Anything up to 
// the first whitespace outside a quoted subtring is accepted. Backslashes are treated as normal 
// characters.

-

// Rules: 2N backslashes + " ==> N backslashes and begin/end quote
//      2N+1 backslashes + " ==> N backslashes + literal "
//         N backslashes     ==> N backslashes

这是我认为的是无论是MSVC C库或.NET框架移植到.NET的核心代码CommandLineToArgvW

下面是在处理一些使用正则表达式的恶作剧,而忽略参数零位我三心二意的尝试。 这是一个有点wizardy。

private static readonly Regex RxWinArgs
  = new Regex("([^\\s\"]+\"|((?<=\\s|^)(?!\"\"(?!\"))\")+)(\"\"|.*?)*\"[^\\s\"]*|[^\\s]+",
    RegexOptions.Compiled
    | RegexOptions.Singleline
    | RegexOptions.ExplicitCapture
    | RegexOptions.CultureInvariant);

internal static IEnumerable<string> ParseArgumentsWindows(string args) {
  var match = RxWinArgs.Match(args);

  while (match.Success) {
    yield return match.Value;
    match = match.NextMatch();
  }
}

测试了它一个公平一点上古怪生成的输出。 这是输出什么样的猴子打完了,并通过运行一个公平的百分比匹配CommandLineToArgvW



Answer 13:

目前,这是我的代码:

    private String[] SplitCommandLineArgument(String argumentString)
    {
        StringBuilder translatedArguments = new StringBuilder(argumentString);
        bool escaped = false;
        for (int i = 0; i < translatedArguments.Length; i++)
        {
            if (translatedArguments[i] == '"')
            {
                escaped = !escaped;
            }
            if (translatedArguments[i] == ' ' && !escaped)
            {
                translatedArguments[i] = '\n';
            }
        }

        string[] toReturn = translatedArguments.ToString().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
        for(int i = 0; i < toReturn.Length; i++)
        {
            toReturn[i] = RemoveMatchingQuotes(toReturn[i]);
        }
        return toReturn;
    }

    public static string RemoveMatchingQuotes(string stringToTrim)
    {
        int firstQuoteIndex = stringToTrim.IndexOf('"');
        int lastQuoteIndex = stringToTrim.LastIndexOf('"');
        while (firstQuoteIndex != lastQuoteIndex)
        {
            stringToTrim = stringToTrim.Remove(firstQuoteIndex, 1);
            stringToTrim = stringToTrim.Remove(lastQuoteIndex - 1, 1); //-1 because we've shifted the indicies left by one
            firstQuoteIndex = stringToTrim.IndexOf('"');
            lastQuoteIndex = stringToTrim.LastIndexOf('"');
        }
        return stringToTrim;
    }

它不转义引号的工作,但它的工作原理为,我已经碰到迄今为止案件。



Answer 14:

这是安东的代码的答复,不与转义引号工作。 我修改了3个名额。

  1. 构造函数用于SplitCommandLineArguments StringBuilder的 ,用\ r更换任何\”
  2. SplitCommandLineArguments for循环 ,我现在替换\ r字符到\”。
  3. 改变了SplitCommandLineArgument方法从私人公共静态

public static string[] SplitCommandLineArgument( String argumentString )
{
    StringBuilder translatedArguments = new StringBuilder( argumentString ).Replace( "\\\"", "\r" );
    bool InsideQuote = false;
    for ( int i = 0; i < translatedArguments.Length; i++ )
    {
        if ( translatedArguments[i] == '"' )
        {
            InsideQuote = !InsideQuote;
        }
        if ( translatedArguments[i] == ' ' && !InsideQuote )
        {
            translatedArguments[i] = '\n';
        }
    }

    string[] toReturn = translatedArguments.ToString().Split( new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries );
    for ( int i = 0; i < toReturn.Length; i++ )
    {
        toReturn[i] = RemoveMatchingQuotes( toReturn[i] );
        toReturn[i] = toReturn[i].Replace( "\r", "\"" );
    }
    return toReturn;
}

public static string RemoveMatchingQuotes( string stringToTrim )
{
    int firstQuoteIndex = stringToTrim.IndexOf( '"' );
    int lastQuoteIndex = stringToTrim.LastIndexOf( '"' );
    while ( firstQuoteIndex != lastQuoteIndex )
    {
        stringToTrim = stringToTrim.Remove( firstQuoteIndex, 1 );
        stringToTrim = stringToTrim.Remove( lastQuoteIndex - 1, 1 ); //-1 because we've shifted the indicies left by one
        firstQuoteIndex = stringToTrim.IndexOf( '"' );
        lastQuoteIndex = stringToTrim.LastIndexOf( '"' );
    }
    return stringToTrim;
}


Answer 15:

我不认为有单引号或^报价C#应用程序。 下面的函数工作对我罚款:

public static IEnumerable<String> SplitArguments(string commandLine)
{
    Char quoteChar = '"';
    Char escapeChar = '\\';
    Boolean insideQuote = false;
    Boolean insideEscape = false;

    StringBuilder currentArg = new StringBuilder();

    // needed to keep "" as argument but drop whitespaces between arguments
    Int32 currentArgCharCount = 0;                  

    for (Int32 i = 0; i < commandLine.Length; i++)
    {
        Char c = commandLine[i];
        if (c == quoteChar)
        {
            currentArgCharCount++;

            if (insideEscape)
            {
                currentArg.Append(c);       // found \" -> add " to arg
                insideEscape = false;
            }
            else if (insideQuote)
            {
                insideQuote = false;        // quote ended
            }
            else
            {
                insideQuote = true;         // quote started
            }
        }
        else if (c == escapeChar)
        {
            currentArgCharCount++;

            if (insideEscape)   // found \\ -> add \\ (only \" will be ")
                currentArg.Append(escapeChar + escapeChar);       

            insideEscape = !insideEscape;
        }
        else if (Char.IsWhiteSpace(c))
        {
            if (insideQuote)
            {
                currentArgCharCount++;
                currentArg.Append(c);       // append whitespace inside quote
            }
            else
            {
                if (currentArgCharCount > 0)
                    yield return currentArg.ToString();

                currentArgCharCount = 0;
                currentArg.Clear();
            }
        }
        else
        {
            currentArgCharCount++;
            if (insideEscape)
            {
                // found non-escaping backslash -> add \ (only \" will be ")
                currentArg.Append(escapeChar);                       
                currentArgCharCount = 0;
                insideEscape = false;
            }
            currentArg.Append(c);
        }
    }

    if (currentArgCharCount > 0)
        yield return currentArg.ToString();
}


Answer 16:

你可以看看我昨天已经发布的代码:

[C#]路径和参数串

它分割一个文件名+参数到字符串[]。 短的路径,环境变量和丢失的文件扩展名进行处理。

(起初它是UninstallString注册表)。



Answer 17:

试试这个代码:

    string[] str_para_linha_comando(string str, out int argumentos)
    {
        string[] linhaComando = new string[32];
        bool entre_aspas = false;
        int posicao_ponteiro = 0;
        int argc = 0;
        int inicio = 0;
        int fim = 0;
        string sub;

        for(int i = 0; i < str.Length;)
        {
            if (entre_aspas)
            {
                // Está entre aspas
                sub = str.Substring(inicio+1, fim - (inicio+1));
                linhaComando[argc - 1] = sub;

                posicao_ponteiro += ((fim - posicao_ponteiro)+1);
                entre_aspas = false;
                i = posicao_ponteiro;
            }
            else
            {
            tratar_aspas:
                if (str.ElementAt(i) == '\"')
                {
                    inicio = i;
                    fim = str.IndexOf('\"', inicio + 1);
                    entre_aspas = true;
                    argc++;
                }
                else
                {
                    // Se não for aspas, então ler até achar o primeiro espaço em branco
                    if (str.ElementAt(i) == ' ')
                    {
                        if (str.ElementAt(i + 1) == '\"')
                        {
                            i++;
                            goto tratar_aspas;
                        }

                        // Pular os espaços em branco adiconais
                        while(str.ElementAt(i) == ' ') i++;

                        argc++;
                        inicio = i;
                        fim = str.IndexOf(' ', inicio);
                        if (fim == -1) fim = str.Length;
                        sub = str.Substring(inicio, fim - inicio);
                        linhaComando[argc - 1] = sub;
                        posicao_ponteiro += (fim - posicao_ponteiro);

                        i = posicao_ponteiro;
                        if (posicao_ponteiro == str.Length) break;
                    }
                    else
                    {
                        argc++;
                        inicio = i;
                        fim = str.IndexOf(' ', inicio);
                        if (fim == -1) fim = str.Length;

                        sub = str.Substring(inicio, fim - inicio);
                        linhaComando[argc - 1] = sub;
                        posicao_ponteiro += fim - posicao_ponteiro;
                        i = posicao_ponteiro;
                        if (posicao_ponteiro == str.Length) break;
                    }
                }
            }
        }

        argumentos = argc;

        return linhaComando;
    }

这是写在葡萄牙。



Answer 18:

这里有一个衬里,其能够完成任务(见一行,做的所有BurstCmdLineArgs(...)方法中的工作)。

不是我会打电话的代码最可读的行,但你可以打破它为了便于阅读的缘故。 这是对目的简单,为所有参数的情况下(如包含在其中分割字符串的字符分隔符的文件名参数)不能很好地工作。

该解决方案在我的解决方案,使用它一直运作良好。 就像我说的,它得到无代码来处理每一个可能的参数格式正阶乘一个老鼠窝完成任务。

using System;
using System.Collections.Generic;
using System.Linq;

namespace CmdArgProcessor
{
    class Program
    {
        static void Main(string[] args)
        {
            // test switches and switches with values
            // -test1 1 -test2 2 -test3 -test4 -test5 5

            string dummyString = string.Empty;

            var argDict = BurstCmdLineArgs(args);

            Console.WriteLine("Value for switch = -test1: {0}", argDict["test1"]);
            Console.WriteLine("Value for switch = -test2: {0}", argDict["test2"]);
            Console.WriteLine("Switch -test3 is present? {0}", argDict.TryGetValue("test3", out dummyString));
            Console.WriteLine("Switch -test4 is present? {0}", argDict.TryGetValue("test4", out dummyString));
            Console.WriteLine("Value for switch = -test5: {0}", argDict["test5"]);

            // Console output:
            //
            // Value for switch = -test1: 1
            // Value for switch = -test2: 2
            // Switch -test3 is present? True
            // Switch -test4 is present? True
            // Value for switch = -test5: 5
        }

        public static Dictionary<string, string> BurstCmdLineArgs(string[] args)
        {
            var argDict = new Dictionary<string, string>();

            // Flatten the args in to a single string separated by a space.
            // Then split the args on the dash delimiter of a cmd line "switch".
            // E.g. -mySwitch myValue
            //  or -JustMySwitch (no value)
            //  where: all values must follow a switch.
            // Then loop through each string returned by the split operation.
            // If the string can be split again by a space character,
            // then the second string is a value to be paired with a switch,
            // otherwise, only the switch is added as a key with an empty string as the value.
            // Use dictionary indexer to retrieve values for cmd line switches.
            // Use Dictionary::ContainsKey(...) where only a switch is recorded as the key.
            string.Join(" ", args).Split('-').ToList().ForEach(s => argDict.Add(s.Split()[0], (s.Split().Count() > 1 ? s.Split()[1] : "")));

            return argDict;
        }
    }
}


Answer 19:

我不知道如果我理解你,但就是字符作为分流的问题,也是里面的文字被发现? (除了它被转义双“?)

如果是的话,我会创建一个for循环,并取代所有实例,其中<“>存在与<|>(或其他‘安全’字样,但要确保,只替换<”>,而不是<“”>

遍历字符串之后,我会做如以前发布的,分割字符串,但现在对人物<|>。



Answer 20:

是的,字符串对象有一个内置的调用的函数Split()采用单个参数,指定的字符,以寻找作为分隔符,并返回字符串在它与单独的值的阵列(串[])。



文章来源: Split string containing command-line parameters into string[] in C#