簡體   English   中英

除非在單引號或雙引號中,否則如何用空格分隔字符串

[英]How do I split a string by spaces except if in single or double quotes

我意識到這個問題已經在這里被問過很多次了。 我已經查看並嘗試了許多答案,但沒有一個對我有用。

我正在使用 C# 創建一個可以接受命令行 arguments 的應用程序。 例如

  1. Start -p:SomeNameValue -h
  2. DisplayMessage -m:Hello
  3. DisplayMessage -m:'Hello World'
  4. DisplayMessage -m:"Hello World"

我的 args 以單個字符串的形式出現。 我需要用空格分隔,除非有單引號或雙引號。 所以上面的結果會是

  1. Start -p:SomeNameValue -h
  2. DisplayMessage -m:Hello
  3. DisplayMessage -m:'Hello World'
  4. DisplayMessage -m:"Hello World"

我在這里找到的答案似乎被打破了。 例如,他們刪除:字符或者根本不工作。 我嘗試過的一些代碼如下:

var res1 = Regex.Matches(payload, @"[\""].+?[\""]|[^ ]+")
    .Cast<Match>()
    .Select(m => m.Value)
    .ToList();
var res2 = payload.Split('"')
    .Select((element, index) => index % 2 == 0  
        ? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
        : new string[] { element })  // Keep the entire item
    .SelectMany(element => element).ToList();
var res3 = Regex
    .Matches(payload, @"\w+|""[\w\s]*""")
    .Cast<Match>()
    .Select(m => m.Groups["match"].Value)
    .ToList();
string[] res4 = Regex.Split(payload, ",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");
Regex regex = new Regex(@"\w+|""[\w\s]*""");
var res5 = regex.Matches(payload).Cast<Match>().ToList();

我只是想按照上面的方法將 arg 分成塊。

這是一個簡單的演示程序,我認為它通過解析字符串完全符合您的要求。

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {       
        string[] testStrings = new string[] {
            "Start -p:SomeNameValue -h",
            "DisplayMessage -m:Hello",
            "DisplayMessage -m:'Hello World'",
            "DisplayMessage -m:\"Hello World\"",
            "DisplayMessage -m:\"'Inside double quotes'\"",
            "DisplayMessage -m:'\"Inside single quotes\"'"              
        };

        foreach (string str in testStrings)
        {
            Console.WriteLine(str);
            string[] parsedStrings = ParseString(str);

            for (int i = 0; i < parsedStrings.Length; i++)
            {
                Console.WriteLine("    " + (i + 1) + ". " + parsedStrings[i]);              
            }
            Console.WriteLine();
        }
    }

    private static string[] ParseString(string str)
    {
        var retval = new List<string>();
        if (String.IsNullOrWhiteSpace(str)) return retval.ToArray();
        int ndx = 0;
        string s = "";
        bool insideDoubleQuote = false;
        bool insideSingleQuote = false;

        while (ndx < str.Length)
        {
            if (str[ndx] == ' ' && !insideDoubleQuote && !insideSingleQuote)
            {
                if (!String.IsNullOrWhiteSpace(s.Trim())) retval.Add(s.Trim());
                s = "";
            }
            if (str[ndx] == '"') insideDoubleQuote = !insideDoubleQuote;
            if (str[ndx] == '\'') insideSingleQuote = !insideSingleQuote;
            s += str[ndx];
            ndx++;
        }
        if (!String.IsNullOrWhiteSpace(s.Trim())) retval.Add(s.Trim());
        return retval.ToArray();
    }
}

該程序將產生以下 output:

Start -p:SomeNameValue -h

1. Start

2. -p:SomeNameValue

3. -h

DisplayMessage -m:Hello

1. DisplayMessage

2. -m:Hello

DisplayMessage -m:'Hello World'

1. DisplayMessage

2. -m:'Hello World'

DisplayMessage -m:"Hello World"

1. DisplayMessage

2. -m:"Hello World"

DisplayMessage -m:"'Inside double quotes'"

1. DisplayMessage

2. -m:"'Inside double quotes'"

DisplayMessage -m:'"Inside single quotes"'

1. DisplayMessage

2. -m:'"Inside single quotes"'

一種方法是使用循環來檢查包含雙引號分隔符的項目,並使用標志變量來確定我們是在帶引號的字符串內部還是外部。 如果我們在帶引號的字符串中,請將當前部分添加到臨時變量中。 當我們退出引用的字符串時,將臨時變量添加到我們的 arguments 集合中。

我認為代碼更不言自明。 請注意,我只允許雙引號用空格分隔參數。 如果您也想允許單引號,則可以將其添加到代碼中:

public static List<string> GetArgs(string cmdLine)
{
    var args = new List<string>();
    if (string.IsNullOrWhiteSpace(cmdLine)) return args;

    var parts = cmdLine.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    var openQuote = false;
    var currentPart = new StringBuilder();

    foreach (var part in parts)
    {
        if (part.Count(c => c == '"') % 2 == 1)
        {
            if (currentPart.Length > 0) currentPart.Append(" ");
            currentPart.Append(part);

            if (openQuote)
            {
                args.Add(currentPart.ToString());
                currentPart.Clear();
            }

            openQuote = !openQuote;
        }
        else if (openQuote)
        {
            if (currentPart.Length > 0) currentPart.Append(" ");
            currentPart.Append(part);
        }
        else
        {
            args.Add(part);
        }
    }

    if (currentPart.Length > 0) args.Add(currentPart.ToString());

    return args;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM