拆分字符串并保留分隔符

时间:2014-05-25 09:30:04

标签: c# regex string split

大家好我一直试图看看我是否可以拆分字符串,将分隔符保留为新字符串数组中的单独元素,但发现它很难。这正是我想要实现的目标....

如果我有字符串"8*(4+x)+7" ...

我将使用运算符和括号进行分割,得到类似...... "8","*", "(", "4", "+", "x", ")", "+", "7" ....

的内容

我在这里已经阅读了许多关于如何使用Regex.Split做到这一点的答案,并尝试了很多但我没有得到我想要的东西。

3 个答案:

答案 0 :(得分:4)

不要拆分 - 匹配!

var equation = "8 * (42+xyz)+7";
var tokens = Regex.Matches(equation, @"\d+|\w+|\S")
    .OfType<Match>()
    .Select(m => m.Value);

regular expression pattern

之一相匹配
  • 一系列数字 - 例如842
  • 一系列单词字符 - 例如xyz(它也会匹配x_2
  • 单个非空白字符 - 例如*(

匹配多次执行(通过Matches),并且每个成功匹配的值都会被选入生成的IEnumerable<string>

与传统的Split不同,这种方法没有明确的分隔符,因为分离只是由每个匹配停止的位置和下一个匹配开始决定的。这也是跳过空白区域的原因:它只是不匹配。

要明确指定运算符或“分隔符”,只需将\S(与任何非空白字符匹配)替换为[+*()](仅匹配指定的运算符和括号)的模式。 / p>

虽然这是一个非常简单的令牌工具,可以完成所请求的任务,但在此阶段添加额外的lexeme信息通常很有用。

答案 1 :(得分:1)

string str = "8400*(413+x)+700";
List<string> lstArray = new List<string>();

 for(int i=0; i<str.Length; i++)
 {
      if (Char.IsNumber(str[i]))
      {
           string sNum = str[i].ToString();

           if ((i + 1) < str.Length)
           {
                 for (int k = i+1; k < str.Length; k++)
                 {
                     if (Char.IsNumber(str[k]) == true)
                     {
                         sNum += str[k].ToString();
                         i = i + 1;
                     }
                     else
                        break;
                  }
           }
           lstArray.Add(sNum);
       }
       else if (Char.IsSymbol(str[i]))
       {
            lstArray.Add(str[i].ToString());                                  
       }
       else if (Char.IsLetter(str[i]))
       {
           string sLetter = str[i].ToString();

           if ((i + 1) < str.Length)
           {
              for (int k = i + 1; k < str.Length; k++)
              {
                  if (Char.IsLetter(str[k]) == true)
                  {
                      sLetter += str[k].ToString();
                      i = i + 1;
                  }
                  else
                      break;
              }
          }
          lstArray.Add(sLetter);
      }
      else if (Char.IsPunctuation(str[i]))
      {                   
          lstArray.Add(str[i].ToString());
      }
  }

以上代码应该有效。 打印值之间使用逗号的列表应如下所示:

 Console.WriteLine(string.Join(",", lstArray.ToArray()));

以下是输入和输出示例:

 //Input     
 8400*(413+xyz)+700

 //Output
 8400,*,(,413,+,xyz,),+,700

或者您可以遍历lstArray

 foreach(string s in lstArray)
     Console.WriteLine(s);

答案 2 :(得分:1)

这有效:

Func<IEnumerable<string>, IEnumerable<char>, IEnumerable<string>> split = null;
split = (ss, cs) =>
{
    if (!cs.Any())
    {
        return ss;
    }
    else
    {
        var c = cs.First();
        return ss.SelectMany(s0 =>
        {
            var parts = s0.Split(c);
            return split(
                parts
                    .Take(1)
                    .Concat(
                        parts
                            .Skip(1)
                            .SelectMany(p => new [] { new string(c, 1), p })),
                cs.Skip(1));
        })
        .Where(s0 => !String.IsNullOrWhiteSpace(s0));
    }
};

(请注意,split的双重赋值是必要的,因为这是一个递归函数。)

所以,如果我从这开始:

var s = "80*(45+xy)+27";
var separators = "*+-/()";

我可以这样做:

var result = split(new [] { s }, separators);

我最终得到了这个:

result