如何拆分以空格分隔的路径列表,其中路径可以包含.NET 2中的空格?

时间:2013-01-09 16:13:07

标签: c# .net visual-studio-2005

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

应该以列表形式阅读:

  • c:\ dir1
  • C:\ DIR2
  • c:\ my files
  • C:\代码
  • 旧照片
  • 新照片

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

4 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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#功夫可以让它变得更简单。我应该补充一点,显然,这个算法会给你带来乱序的项目......所以如果这很重要......这不是一个好的解决方案。

答案 2 :(得分: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;
}

答案 3 :(得分: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