【问题标题】:Detect particular tokens in a string. C#检测字符串中的特定标记。 C#
【发布时间】:2010-11-25 13:29:47
【问题描述】:

我有一个非常大的字符串 (HTML),在这个 HTML 中有特定的标记,所有标记都以“#”开头并以“#”结尾

简单的例子

<html>
<body>
      <p>Hi #Name#, You should come and see this #PLACE# - From #SenderName#</p>
</body>
</html>

我需要一个代码来检测这些令牌并将其放入列表中。 0 - #姓名# 1 - #地点# 2 - #发件人姓名#

我知道我也许可以使用正则表达式,无论如何你有什么想法吗?

【问题讨论】:

    标签: c# .net string


    【解决方案1】:

    你可以试试:

    // using System.Text.RegularExpressions;
    // pattern = any number of arbitrary characters between #.
    var pattern = @"#(.*?)#";
    var matches = Regex.Matches(htmlString, pattern);
    
    foreach (Match m in matches) {
        Console.WriteLine(m.Groups[1]);
    }
    

    this SO 问题中得到启发。

    【讨论】:

    • +1 是 - 也考虑使用非贪婪的 .* 匹配;虽然应该是.+?
    • 这会无法解析这样的文本:Hi #Name#where#PLACE# more text,还是我误解了 RegEx 的工作原理。对于 OP 来说,这也可能不是一个有效的问题,所以这只是出于我自己的好奇心 :)
    • 是的。我认为Hi #Name#where#PLACE# more text 会失败。
    • 查看 VladV 的回答。它实际上会很好。然后我今天也学到了一些新东西:)
    【解决方案2】:

    是的,您可以使用正则表达式。

    string test = "Hi #Name#, You should come and see this #PLACE# - From #SenderName#";
    Regex reg = new Regex(@"#\w+#");
    foreach (Match match in reg.Matches(test))
    {
        Console.WriteLine(match.Value);
    }
    

    正如您可能已经猜到的,\w 表示任何字母数字字符。 + 表示它可能出现 1 次或多次。你可以在这里找到更多信息msdn doc(对于.Net 4。你也可以在那里找到其他版本)。

    【讨论】:

      【解决方案3】:

      如果您愿意,可以使用不带Regex 的变体:

      var splitstring = myHtmlString.Split('#');
      var tokens = new List<string>();
      for( int i = 1; i < splitstring.Length; i+=2){
        tokens.Add(splitstring[i]);
      }   
      

      【讨论】:

      • 为什么要对此投反对票?它将产生所需的结果。我会感谢投票者的理由。
      • 它有效,我会给它一个 +1 来弥补太喜欢​​正则表达式的人。
      【解决方案4】:
      foreach (Match m in Regex.Matches(input, @"#\w+#"))
          Console.WriteLine("'{0}' found at index {1}.",  m.Value, m.Index);
      

      【讨论】:

      • 这将如何正确解析Hi #Name#where#PLACE# more text。只要它是一个单词,这是否也解析散列“外部”的单词?还是我在这里弄错了?
      • 刚刚验证 - 在您的示例中,它给出了“#Name#”和“#PLACE#”。当考虑多个匹配时,它们中的每一个都在前一个结束之后开始 - 即在“#Name#”匹配之后,它开始在第二个井号之后寻找下一个匹配。
      • +1:太完美了。我现在明白为什么了,因为 # 实际上被第一个匹配“使用”了,因此第二个也不能使用。感谢您的启发。
      【解决方案5】:

      试试这个

      var result = html.Split('#')
                          .Select((s, i) => new {s, i})
                          .Where(p => p.i%2 == 1)
                          .Select(t => t.s);
      

      解释:

      line1 - 我们用字符'#'分割文本

      line2 - 我们选择一个新的匿名类型,其中包括字符串在数组中的位置,以及字符串本身

      line3 - 我们将匿名对象列表过滤为具有奇数索引值的对象 - 有效地选择“每隔一个”字符串 - 这适合查找那些包含在哈希字符中的字符串,而不是那些外部的字符串

      line4 = 我们去掉索引器,只返回匿名类型的字符串

      【讨论】:

      • +1 用于使用 Select 重载,除了我认为所有人都知道的值之外,它还为您提供索引。
      • 很好很简短,但您介意再解释一下吗?啜?也许使用“解释”变量会使其对其他人更具教育意义。
      【解决方案6】:

      用途:

      MatchCollection matches = Regex.Matches(mytext, @"#(\w+)#");
      
      foreach(Match m in matches)
      {
          Console.WriteLine(m.Groups[1].Value);
      }
      

      【讨论】:

        【解决方案7】:

        天真的解决方案:

        var result = Regex
            .Matches(html, @"\#([^\#.]*)\#")
            .OfType<Match>()
            .Select(x => x.Groups[1].Value)
            .ToList();
        

        【讨论】:

          【解决方案8】:

          Linq 解决方案:

                  string s = @"<p>Hi #Name#, 
                    You should come and see this #PLACE# - From #SenderName#</p>";
          
                  var result = s.Split('#').Where((x, y) => y % 2 != 0).Select(x => x);
          

          【讨论】:

          • 很好很简短,但您介意再解释一下吗? x,y?也许使用“解释”变量会使其对其他人更具教育意义。
          • @BerggreenDK 当然,方法Where 是重载的。 (x,y) 是一对,其中x 是集合的当前项,y 是该项的索引。是的,你是对的,我本可以使用Where(item,index) 以获得更好的可读性。在我只选择奇数字符串之后,因为它们是我们需要的。
          【解决方案9】:

          Regex.Matches 方法与类似的模式一起使用

          #[^#]+# 用于模式。

          这可能是最天真的方式。

          如果您希望避免在输出匹配中包含“#”字符,则可能需要对此进行调整,可能需要进行环顾:

          (?&lt;=#)[^#]+(?=#)

          (这个匹配值是 'hello' 而不是 '#hello#' - 所以你不必再做任何修剪)

          【讨论】:

            【解决方案10】:

            这会根据要求为您提供令牌列表:

            var tokens = new List<string>();
            var matches = new Regex("(#.*?#)").Matches(html);
            
            foreach (Match m in matches) 
                tokens.Add(m.Groups[1].Value);
            

            编辑:如果您希望包含井号字符,只需将它们移到正则表达式字符串中的括号外(请参阅 Pablo 的回答)。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-10-21
              • 1970-01-01
              • 2015-10-30
              • 2016-03-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-05-01
              相关资源
              最近更新 更多