拆分具有空格的字符串,除非它们包含在"引号"中?

Tea*_*hme 46 c# split

简单来说:

string streamR = sr.ReadLine();  // sr.Readline results in:
                                 //                         one "two two"
Run Code Online (Sandbox Code Playgroud)

我希望能够将它们保存为两个不同的字符串,删除所有空格除了引号之间的空格.因此,我需要的是:

string 1 = one
string 2 = two two
Run Code Online (Sandbox Code Playgroud)

到目前为止,我发现有效的是以下代码,但它删除了引号内的空格.

//streamR.ReadLine only has two strings
  string[] splitter = streamR.Split(' ');
    str1 = splitter[0];
    // Only set str2 if the length is >1
    str2 = splitter.Length > 1 ? splitter[1] : string.Empty;
Run Code Online (Sandbox Code Playgroud)

这个的输出变成了

one
two
Run Code Online (Sandbox Code Playgroud)

我已经研究过正则表达式来分隔空格,除非引用但是我似乎无法获得正则表达式来工作/理解代码,特别是如何分割它们以便它们是两个不同的字符串.那里的所有代码都给我一个编译错误(我正在使用System.Text.RegularExpressions)

I4V*_*I4V 51

string input = "one \"two two\" three \"four four\" five six";
var parts = Regex.Matches(input, @"[\""].+?[\""]|[^ ]+")
                .Cast<Match>()
                .Select(m => m.Value)
                .ToList();
Run Code Online (Sandbox Code Playgroud)

  • 命令参数拆分失败:`test --file="some file.txt"` 拆分为 3 个字符串,而不是两个。预期输出将是:`test` 和 `--file="some file.txt"` 我不是正则表达式专家,所以无法修复它。:( (2认同)
  • 找到这个有效的正则表达式:`Regex.Split(ConsoleInput,"(?<= ^ [^ \"]*(?:\"[^ \"]*\"[^ \"]*)*)(?= (?:[^ \"]*\"[^ \"]*\")*[^ \"]*$)");`在http://stackoverflow.com/a/4780801/953414并附上解释它是如何工作的. (2认同)
  • 请解释一下你的答案,仅仅给出一段代码并不能教会任何东西,并且该用户将来可能会提出更多有关该主题的问题,至少提供学习参考。 (2认同)

Céd*_*non 31

你甚至可以在没有Regex的情况下做到这一点:LINQ表达式String.Split可以完成这项工作.

您可以先拆分字符串,"然后在结果数组中仅拆分带有偶数索引的元素 .

var result = myString.Split('"')
                     .Select((element, index) => index % 2 == 0  // If even index
                                           ? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)  // Split the item
                                           : new string[] { element })  // Keep the entire item
                     .SelectMany(element => element).ToList();
Run Code Online (Sandbox Code Playgroud)

For the string:

This is a test for "Splitting a string" that has white spaces, unless they are "enclosed within quotes"
Run Code Online (Sandbox Code Playgroud)

It gives the result:

This
is
a
test
for
Splitting a string
that
has
white
spaces,
unless
they
are
enclosed within quotes
Run Code Online (Sandbox Code Playgroud)

UPDATE

string myString = "WordOne \"Word Two\"";
var result = myString.Split('"')
                     .Select((element, index) => index % 2 == 0  // If even index
                                           ? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)  // Split the item
                                           : new string[] { element })  // Keep the entire item
                     .SelectMany(element => element).ToList();

Console.WriteLine(result[0]);
Console.WriteLine(result[1]);
Console.ReadKey();
Run Code Online (Sandbox Code Playgroud)

UPDATE 2

How do you define a quoted portion of the string?

We will assume that the string before the first "是非引用的.

然后,引用放在第一个"和第二个之间的字符串".第二个"和第三个之间的字符串"是非引用的.引用第三个和第四个之间的字符串,......

一般规则是:引用"第(2*n-1)th(奇数)和第(2*n)th(偶数)之间的每个字符串".(1)

有什么关系String.Split

String.SSplit使用默认的StringSplitOption(定义为StringSplitOption.None)创建一个包含1个字符串的列表,然后在列表中为找到的每个拆分字符添加一个新字符串.

因此,在第一个之前",字符串在分割数组中的索引0处,在第一个和第二个之间",字符串在数组中的索引1处,在第三个和第四个之间,索引2,...

一般规则是:第n个和第(n + 1)个之间的字符串在"数组中的索引n处.(2)

给定的(1)(2),我们可以得出这样的结论:引部处于分裂阵列中奇数索引.


psu*_*003 9

由于自定义解析器可能更适合此.

当我有一个涉及括号和空格的特定(并且非常奇怪)的解析要求时,这是我写过的东西,但它足够通用,它应该适用于几乎任何分隔符和文本限定符.

public static IEnumerable<String> ParseText(String line, Char delimiter, Char textQualifier)
{

    if (line == null)
        yield break;

    else
    {
        Char prevChar = '\0';
        Char nextChar = '\0';
        Char currentChar = '\0';

        Boolean inString = false;

        StringBuilder token = new StringBuilder();

        for (int i = 0; i < line.Length; i++)
        {
            currentChar = line[i];

            if (i > 0)
                prevChar = line[i - 1];
            else
                prevChar = '\0';

            if (i + 1 < line.Length)
                nextChar = line[i + 1];
            else
                nextChar = '\0';

            if (currentChar == textQualifier && (prevChar == '\0' || prevChar == delimiter) && !inString)
            {
                inString = true;
                continue;
            }

            if (currentChar == textQualifier && (nextChar == '\0' || nextChar == delimiter) && inString)
            {
                inString = false;
                continue;
            }

            if (currentChar == delimiter && !inString)
            {
                yield return token.ToString();
                token = token.Remove(0, token.Length);
                continue;
            }

            token = token.Append(currentChar);

        }

        yield return token.ToString();

    } 
}
Run Code Online (Sandbox Code Playgroud)

用法是:

var parsedText = ParseText(streamR, ' ', '"');
Run Code Online (Sandbox Code Playgroud)

  • @mischka你是对的.您赢得了4年以上未被发现的语法错误 (3认同)

Joh*_*ner 9

您可以使用属于命名空间的TextFieldParserMicrosoft.VisualBasic.FileIO.(您需要添加Microsoft.VisualBasic对项目的引用.):

string inputString = "This is \"a test\" of the parser.";

using (MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(inputString)))
{
    using (Microsoft.VisualBasic.FileIO.TextFieldParser tfp = new TextFieldParser(ms))
    {
        tfp.Delimiters = new string[] { " " };
        tfp.HasFieldsEnclosedInQuotes = true;
        string[] output = tfp.ReadFields();

        for (int i = 0; i < output.Length; i++)
        {
            Console.WriteLine("{0}:{1}", i, output[i]);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这会产生输出:

0:This
1:is
2:a test
3:of
4:the
5:parser.
Run Code Online (Sandbox Code Playgroud)