【问题标题】:How to split a string on the 3rd occurence of a char C#如何在 char C# 的第 3 次出现时拆分字符串
【发布时间】:2017-04-14 12:29:18
【问题描述】:

我想知道有没有办法在第 3 次出现 char 时拆分字符串?之前拆分时我使用的是:

line.Substring(line.LastIndexOf(']') +1);

我没有意识到我的一些字符串比其他字符串有额外的方括号,所以理想情况下我需要在第 3 次出现 ']' 时拆分,因为这是每个字符串的相同位置。

输入:[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] 文件不存在:

输出:

[2014 年 12 月 17 日星期三 14:40:28] [错误] [客户端 143.117.101.166]

文件不存在:

【问题讨论】:

  • 你能提供输入和预期输出吗?
  • 问题已用输入和预期输出进行编辑
  • 这是一个SO post,它有一个AllIndesOff() 方法。你可以使用它。
  • c#中没有(built-in)这样的功能。您必须实现自己的自定义方法来查找传递的 char 和 n 的 N-th 出现。
  • 我不知道您的目标是什么,但看起来正则表达式可能是选择该字符串所需部分的好方法。

标签: c#


【解决方案1】:

你需要先拆分字符串,然后取第三个的索引]

line.Substring(line.IndexOf(line.Split(']')[3]));

或者更简单,就像你说的 ] 的第三个索引是一样的,把它固定

line.Substring(59);

【讨论】:

  • 这个答案用最少的代码完成了我想要的。谢谢!
【解决方案2】:

这个输入可以用正则表达式匹配:

\[[^\]]*\]\s*\[[^\]]*\]\s*\[[^\]]*\]

由于转义序列,这看起来很吓人,但结构非常简单:它匹配三个出现的 [ + 零个或多个非] + ],由零个或多个空格分隔。

var s = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist:";
var r = new Regex(@"(\[[^\]]*\]\s*\[[^\]]*\]\s*\[[^\]]*\])(.*)$");
var m = r.Match(s);
if (m.Success) {
    Console.WriteLine("Prefix: {0}", m.Groups[1]);
    Console.WriteLine("Error: {0}", m.Groups[2]);
}

Demo.

【讨论】:

  • 我在尝试实现这段代码时很困惑,我可以给你一些背景知识,然后看看我是否能理解更多吗?
  • 作为示例提供的代码行只是 .txt 文件中的一行,在这种情况下是错误日志。在一个while循环中,我正在读取每一行(每一行在IP末尾都有完全相同的格式,即']'的第三次出现)并将其拆分并插入到数组中。所以目前我用方括号拆分它是可以的,但是对于错误消息,我需要它在第 3 次出现 ']' 时拆分并取出字符串的其余部分。你能帮我理解如何实现吗?
  • @Michael 我修改了正则表达式以匹配该行的其余部分,并将其捕获到第 2 组中。见编辑。
【解决方案3】:

使用正则表达式解决问题,这将捕获带有[]的内容

string input = " [Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist";
var regex = new Regex("\\[(.*?)\\]");
var matches = regex.Matches(input);
foreach (var match in matches) // e.g. you can loop through your matches like this
{
   //yourmatch
}

【讨论】:

    【解决方案4】:

    在这种情况下,我会选择一个简单的拆分:

    var items = line.Split(new[]{']','['},StringSplitOptions.RemoveEmptyEntries);
    if (items.Count > 3) { 
       /* use items[2], or whatever you need... */ 
    }
    

    因为第一个项目总是用括号括起来并且格式相同,所以这会起作用。

    【讨论】:

      【解决方案5】:

      好的,据我所知,C# 没有内置函数来满足您的需求。使用正则表达式是您可以使用的替代方法。

      如果没有,还有另一种方法可以获得您想要的结果,但这仅适用于这些特定的字符串集。但同样,REGEX 也有同样的问题。

      在你的字符串中,如果你观察到] 的前两次出现总是跟在[ 之后

      我的建议是,每当您找到] 的索引时,您只需检查字符串中的下一个字符,如果下一个字符不是[,则只需拆分。

      有无数种方法可以解决您的问题,选择一种使您的代码最模块化的方法。

      希望这会有所帮助。

      【讨论】:

        【解决方案6】:

        如果这是一项常见任务,您可以创建一个扩展方法,为您提供所需角色所在的所有位置,例如:

        static class ExtMethods
        {
            public static IEnumerable<int> IndexesOf(this string str, char c)
            {
                for (int i = 0; i < str.Length; i++)
                {
                    if (str[i] == c)
                    yield return i;
                }
            }
        }
        

        然后你可以得到第三个] 的位置,比如:

        int thirdPos = str.IndexesOf(']').Take(3).Last();
        

        【讨论】:

          【解决方案7】:

          您可以使用 LINQ:

          string input = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist:";
          
          var result = input.Select((ch, ind) => new { ch, ind }).Where(x => x.ch == ']').Skip(2).FirstOrDefault();
          
          string output = input.Substring(result.ind + 1);
          

          【讨论】:

            【解决方案8】:

            使用 Linq 的另一种可能性:

            (从字符串中取出字符,直到看到三个右方括号,然后将输出作为数组发送回 String 构造函数。)

            static void Main(string[] args)
            {
                string test = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist:";
            
                var result = SplitOnChar(test, ']', 3);
            
                Debug.WriteLine(result.Item1);
                Debug.WriteLine(result.Item2);
            }
            
            static Tuple<string, string> SplitOnChar(string input, char c, int occurrence)
            {
                int charCount = 0;
                string firstPart = new String(input.TakeWhile(x => (x == ']' ? charCount++ : charCount) < 3).ToArray());
                string lastPart = input.Substring(firstPart.Length);
                return Tuple.Create(firstPart, lastPart);
            }
            

            归功于该技术的这个答案:LINQ, simplifying expression - take while sum of taken does not exceed given value

            【讨论】:

              【解决方案9】:

              我会这样做:

              public static class SplitExtension
              {
                  public static string[] Split(this string self, char separator, int occurrence)
                  {
                      return self.Split(new string(separator, 1), occurrence);
                  }
              
                  public static string[] Split(this string self, string separator, int occurrence)
                  {
                      string[] chunks = self.Split(new[] { separator }, StringSplitOptions.None);
                      string firstPart = string.Join(separator, chunks.Take(occurrence)) + separator;
                      string secondPart = string.Join(separator, chunks.Skip(occurrence));
                      return new string[] { firstPart, secondPart };
                  }
              }
              

              ...然后像这样使用它:

              string input = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166] File does not exist";
              string[] output = input.Split(']', 3);
              
              // output[0] = "[Wed Dec 17 14:40:28 2014] [error] [client 143.117.101.166]";
              // output[1] = " File does not exist";
              

              【讨论】:

                猜你喜欢
                • 2019-04-02
                • 1970-01-01
                • 2021-08-12
                • 1970-01-01
                • 1970-01-01
                • 2021-08-10
                • 2014-10-12
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多