【问题标题】:Find all words enclosed within @{{Word}}@ or {{Word}} from string从字符串中查找包含在 @{{Word}}@ 或 {{Word}} 中的所有单词
【发布时间】:2020-12-24 09:12:13
【问题描述】:

我正在编写代码来提取包含在 @{{}}@ 和 {{}} 中的所有单词,到目前为止,我已经在网上搜索并发现以下代码按预期工作。

string sampleString = "A @{{Quick}}@ brown @{{fox}}@ jumps @{{over}}@ a lazy {{dog}}.";
List<string> keywordList = new List<string>();
MatchCollection matchedCollection = Regex.Matches(sampleString, @"(@{{(.*?)}}@|{{(.*?)}})");

foreach (Match m in matchedCollection)
{
    keywordList.Add(m.ToString());
}

上面的代码工作正常,它给了我下面列出的 4 个项目,这是正确的。

  1. @{{Quick}}@
  2. @{{Fox}}@
  3. @{{结束}}@
  4. {{狗}}

但是,当单词没有正确括在括号/模式中时,就会出现问题。例如,如果我的字符串格式不正确,如下所示,我会得到不正确的结果。

string sampleString = "A @{{Quick}}@ brown @{{fox jumps @{{over}}@ a lazy {{dog}}.";

具有上述字符串输入的代码将在列表中给我三个项目。

当前结果:

  1. @{{Quick}}@
  2. @{{狐狸跳了@{{over}}@
  3. {{狗}}

预期结果

  1. @{{Quick}}@
  2. @{{over}}@
  3. {{狗}}

任何纠正此问题的建议将不胜感激。

【问题讨论】:

  • 我建议你所拥有的一切都很好,任何问题,比如你的例子,都应该通过清理数据来处理。
  • 根据定义,@{{fox jumps @{{over}}@ 是正确的。除非使用“单词”,否则您的意思是 \S(任何不是空格)而不是 .(任何字符)
  • 我认为在您的示例中,您可以将点 . 替换为 [^{]
  • 嗨@xanatos,我用\S 替换了.,它起作用了。我的关键字没有任何空格,所以这会起作用。

标签: c# .net regex


【解决方案1】:

如果你想要的只是里面没有空格的单词,那么你可以使用\S 而不是.(任何不是空格的字符,而不是任何字符)

MatchCollection matchedCollection = Regex.Matches(sampleString, @"(@{{(\S*?)}}@|{{(\S*?)}})");

【讨论】:

    【解决方案2】:

    正则表达式中的重复似乎是多余的,除非您真的很想知道 @ 是否存在。如果您要剥离它们,那么Regex.Matches(sampleString, @"{{(\S*?)}}") 就可以了

    【讨论】:

      【解决方案3】:

      如果双花括号应该是精确的 2,您可以使用环视来断言之前和之后没有更多的花括号。

      (@?)(?<!{){{(?!{)\S+?(?<!})}}(?!})\1
      

      说明

      • (@?) 捕获组 1,匹配可选的 @
      • (?&lt;!{){{(?!{) 匹配 {{ 之前或之后没有 {
      • \S+? 匹配至少 1 次以上的非空白字符
      • (?&lt;!})}}(?!}) 匹配 }} 之前或之后没有 }
      • \1 反向引用组 1 中捕获的内容

      .NET regex demo

      如果多于2个花括号没问题,可以省略lookarounds

      (@?){{\S+?}}\1
      

      .NET regex demo

      【讨论】:

      • 很想知道怎么写规则可以处理这个字符串A @{{Quick}}@ brown @{{foxjumps@{{over}}@ a lazy {{dog}}.。我正在尝试使用正向模式但不能这样做。你能帮忙吗?非常感谢。
      • @MichaelMao 你是这个意思吗? (@?)(?&lt;!{){{(?!{)(?:(?!{{)\S)+?(?&lt;!})}}(?!})\1regex101.com/r/kQh2h8/1
      • 谢谢你。看起来不错,但现在对我来说太复杂了,无法理解。
      • 我认为不要使用\S 并使用.*?,但在第一个@{{ 之后和第一个}}@ 之前排除@{{
      • 我的规则是(@{{(.*?)(?!@{{)}}@) 意味着在}}@ 之前不能有两个@{{
      【解决方案4】:

      您不必担心匹配项是否包含空格,请使用适当的正则表达式,例如

      (@)?{{(?:(?!@{{).)*?}}(?(1)@|)
      

      proof

      C# 代码

      var matchedCollection = Regex.Matches(sampleString, @"(@)?{{(?:(?!@{{).)*?}}(?(1)@|)", RegexOptions.Singleline);
      

      说明

      --------------------------------------------------------------------------------
        (                        group and capture to \1 (optional):
      --------------------------------------------------------------------------------
          @                        '@'
      --------------------------------------------------------------------------------
        )?                       end of \1
      --------------------------------------------------------------------------------
        {{                       '{{'
      --------------------------------------------------------------------------------
        (?:                      group, but do not capture (0 or more times
                                 (matching the least amount possible)):
      --------------------------------------------------------------------------------
          (?!                      look ahead to see if there is not:
      --------------------------------------------------------------------------------
            @{{                      '@{{'
      --------------------------------------------------------------------------------
          )                        end of look-ahead
      --------------------------------------------------------------------------------
          .                        any character (including \n
                                   with RegexOptions.Singleline)
      --------------------------------------------------------------------------------
        )*?                      end of grouping
      --------------------------------------------------------------------------------
        }}                       '}}'
      --------------------------------------------------------------------------------
        (?(1)                    if back-reference \1 matched, then:
      --------------------------------------------------------------------------------
          @                        '@'
      --------------------------------------------------------------------------------
         |                        else:
      --------------------------------------------------------------------------------
                                   succeed
      --------------------------------------------------------------------------------
        )                        end of conditional on \1
      

      【讨论】:

        猜你喜欢
        • 2014-11-14
        • 1970-01-01
        • 2019-08-07
        • 1970-01-01
        • 2012-06-28
        • 1970-01-01
        • 1970-01-01
        • 2015-02-17
        • 2017-03-02
        相关资源
        最近更新 更多