[英]How do I split a string by spaces except if in single or double quotes
I realize this question has been asked many times here.我意识到这个问题已经在这里被问过很多次了。 I have looked at and tried many of the answers but none of them work for me.
我已经查看并尝试了许多答案,但没有一个对我有用。
I am creating an application using C# that can accept command line arguments.我正在使用 C# 创建一个可以接受命令行 arguments 的应用程序。 eg
例如
Start -p:SomeNameValue -h
DisplayMessage -m:Hello
DisplayMessage -m:'Hello World'
DisplayMessage -m:"Hello World"
My args come in as a single string.我的 args 以单个字符串的形式出现。 I need to split by spaces except where there are single or double quotes.
我需要用空格分隔,除非有单引号或双引号。 So the above would end up as
所以上面的结果会是
Start
-p:SomeNameValue
-h
Start
-p:SomeNameValue
-h
DisplayMessage
-m:Hello
DisplayMessage
-m:Hello
DisplayMessage
-m:'Hello World'
DisplayMessage
-m:'Hello World'
DisplayMessage
-m:"Hello World"
DisplayMessage
-m:"Hello World"
The answers I have found on here seem to break.我在这里找到的答案似乎被打破了。 eg They remove the
:
character or just don't work at all.例如,他们删除
:
字符或者根本不工作。 Some of the code I've tried as follows:我尝试过的一些代码如下:
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();
I simply want to split the arg into blocks as per above.我只是想按照上面的方法将 arg 分成块。
Here is a simple demo program that I think does exactly what you want by parsing the string.这是一个简单的演示程序,我认为它通过解析字符串完全符合您的要求。
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();
}
}
This program will produce the following output:该程序将产生以下 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"'
One way to do this would be to use a loop to check for items that contain the double-quote delimiter and use a flag variable to determine if we're inside or outside a quoted string.一种方法是使用循环来检查包含双引号分隔符的项目,并使用标志变量来确定我们是在带引号的字符串内部还是外部。 If we're inside the quoted string, add the current part to a temporary variable.
如果我们在带引号的字符串中,请将当前部分添加到临时变量中。 When we exit the quoted string, add the temporary variable to our arguments collection.
当我们退出引用的字符串时,将临时变量添加到我们的 arguments 集合中。
I think the code is more self-explanatory.我认为代码更不言自明。 Note that I'm only allowing double quotes to delimit an argument with spaces.
请注意,我只允许双引号用空格分隔参数。 If you want to allow single quotes as well, it's something you can add to the code:
如果您也想允许单引号,则可以将其添加到代码中:
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.