0

例如: c:\dir1 c:\dir2 "c:\my files" c:\code "old photos" "new photos"

应作为列表阅读:

  • c:\目录1
  • c:\dir2
  • c:\我的文件
  • c:\代码
  • 老照片
  • 新照片

我可以编写一个线性解析字符串的函数,但想知道.NET 2.0工具箱是否有任何可以使用的酷技巧?

4

4 回答 4

3

因为你必须击中每个角色,我认为蛮力会给你最好的表现。
这样你就可以准确地击中每个角色一次。
并且它限制了执行的比较次数。

static void Main(string[] args)
{
    string input = @"c:\dir1 c:\dir2 ""c:\my files"" c:\code ""old photos"" ""new photos""";
    List<string> splitInput = MySplit(input);
    foreach (string s in splitInput)
    {
        System.Diagnostics.Debug.WriteLine(s);
    }
    System.Diagnostics.Debug.WriteLine(input);
}

public static List<string> MySplit(string input)
{
    List<string> split = new List<string>();
    StringBuilder sb = new StringBuilder();
    bool splitOnQuote = false;
    char quote = '"';
    char space = ' ';
    foreach (char c in input.ToCharArray())
    {
        if (splitOnQuote)
        {
            if (c == quote)
            {
                if (sb.Length > 0)
                {
                    split.Add(sb.ToString());
                    sb.Clear();
                }
                splitOnQuote = false;
            }
            else { sb.Append(c); }
        }
        else
        {
            if (c == space)
            {
                if (sb.Length > 0)
                {
                    split.Add(sb.ToString());
                    sb.Clear();
                }
            }
            else if (c == quote)
            {
                if (sb.Length > 0)
                {
                    split.Add(sb.ToString());
                    sb.Clear();
                }
                splitOnQuote = true;
            }

            else { sb.Append(c); }
        }
    }
    if (sb.Length > 0) split.Add(sb.ToString());      
    return split;
}
于 2013-01-09T22:04:15.617 回答
1

通常对于这类问题,可以开发一个正则表达式来解析字段。( "(.*?)" )会给你引号中的所有字符串值。您可以从字符串中删除所有这些值,然后在所有引用的项目都出来后对空间进行简单的拆分。

static void Main(string[] args)
        {
            string myString = "\"test\" test1 \"test2 test3\" test4 test6 \"test5\"";
            string myRegularExpression = @"""(.*?)""";
            List<string> listOfMatches = new List<string>();

            myString = Regex.Replace(myString, myRegularExpression, delegate(Match match)
            {
                string v = match.ToString();
                listOfMatches.Add(v);
                return "";
            });

            var array = myString.Split(' ');
            foreach (string s in array)
            {
                if(s.Trim().Length > 0)
                    listOfMatches.Add(s);
            }

            foreach (string match in listOfMatches)
            {
                Console.WriteLine(match);
            }
            Console.Read();

        }

不幸的是,我认为没有任何 C# 功夫可以让它变得更简单。很明显,我应该补充一点,这个算法会给你乱序的项目......所以如果这很重要......这不是一个好的解决方案。

于 2013-01-09T17:30:40.257 回答
1

这是一个仅限正则表达式的解决方案,它捕获空格分隔和引用的路径。带引号的路径被去掉引号,多个空格不会导致空列表条目。将引用路径与未引用路径混合而没有中间空格的边缘情况被解释为多个条目。

可以通过禁用未使用组的捕获来优化它,但我选择了更高的可读性。

static Regex re = new Regex(@"^([ ]*((?<r>[^ ""]+)|[""](?<r>[^""]*)[""]))*[ ]*$");
public static IEnumerable<string> RegexSplit(string input)
{
    var m = re.Match(input ?? "");
    if(!m.Success)
        throw new ArgumentException("Malformed input.");

    return from Capture capture in m.Groups["r"].Captures select capture.Value;
}
于 2013-01-10T08:08:30.167 回答
0

假设空格充当分隔符,除非用引号括起来(以允许路径包含空格),我建议使用以下算法:

ignore_space = false;
i = 0;
list_of_breaks=[];

while(i <  input_length)
{
  if(charat(i) is a space and ignore_space is false)
  {
    add i to list_of_breaks;
  }
  else if(charat(i) is a quote)
  {
    ignore_space = ! ignore_space
  }
}

split the input at the indices listed in list_of_breaks
于 2013-01-09T17:42:39.873 回答