【问题标题】:Regex doesn't match as expected正则表达式与预期不匹配
【发布时间】:2018-05-17 15:18:25
【问题描述】:

我正在尝试编写一个正则表达式来匹配以下文本:

  • 一个字母fst
  • 多次:
    • 至少一位数字
    • 一个字母fst

这是我想出的正则表达式:(f|s|t)(\d+(f|s|t))*,但它似乎不起作用。

输入:f20s30t

预期匹配:

  • f
  • 20 秒
  • 30吨

实际匹配:

  • f
  • 30t
  • t

为什么我的正则表达式错误?

编辑:我正在使用this 方法来拆分输入。

【问题讨论】:

  • “匹配”是指捕获,对吧?目前还不太清楚你在做什么。实际上,您可能只会得到与\d*[fst] 的多个匹配项。在 .NET 中,您可以通过访问与某个组相关的捕获集合来获取所有捕获。它是整个字符串还是较长文本的一部分?
  • @WiktorStribiżew 我在 C# 中使用正则表达式拆分,但我认为这与问题无关。您可以在 regex101.com 中自己测试正则表达式
  • 哦,这非常相关,因为您不应该在 regex101 测试 .NET 正则表达式模式,因为它不支持 .NET 正则表达式。那么,这是整个字符串还是较长文本的一部分?
  • 我认为您对匹配组比较感兴趣。你是?您只给出了一个示例-当您向陌生人询问正则表达式时还不够。举几个正面的例子和负面的例子。
  • @WiktorStribiżew 我编辑了问题,谢谢

标签: c# regex


【解决方案1】:

由于您使用的是 C#,您可以匹配一个带有模式的字符串并访问每个重复捕获组的捕获集合:

var s = "f20s30t";
var m = Regex.Match(s, @"^([fst])(\d+[fst])*$");
if (m.Success)
{
    Console.WriteLine(m.Groups[1].Value);
    foreach (var g in m.Groups[2].Captures.Cast<Capture>().Select(t => t.Value))
        Console.WriteLine(g);
}

这种方法的优点是它还验证字符串,你不会得到像TEXT random f20s30t here....这样的字符串的结果。

查看C# demo,输出

f
20s
30t

这里是regex demo

详情

  • ^ - 字符串的开头
  • ([fst]) - 捕获组 1:fst
  • (\d+[fst])* - 0 次或多次重复(捕获到第 2 组,每个值保存在组堆栈中):
    • \d+ - 1 位以上
    • [fst] - fst
  • $ - 字符串结束。

【讨论】:

    【解决方案2】:

    按照您的示例代码进行:

    ^([fst]|[0-9]+[fst])$
    
    • ^: 字符串开始
    • [fst]fst 之一
    • |:或者
    • [0-9]+:一位或多位数字
    • [fst]fst 之一
    • $: 字符串结束

    在 C# 中:

    using System;
    using System.Text.RegularExpressions;
    
    public class Program
    {
        public static void Main()
        {
            string input = "f20s30t";
            string pattern = "([fst]|[0-9]+[fst])";
            string[] substrings = Regex.Split(input, pattern);
            foreach (string match in substrings)
            {
                Console.WriteLine("'{0}'", match);
            }
        }
    }
    
    //
    //f
    //
    //20s
    //
    //30t
    

    .NET Fiddle

    Regex101

    【讨论】:

      【解决方案3】:

      在正则表达式世界中,(f|s|t) 等于 [fst],但相比之下有一些缺点。所以用后者(一个字符类)代替前者。使用split 方法,您可以对此进行拆分:

      (?<=[fts])(?=\d+[fts])
      

      Above regex 匹配来自[fts] 的字符与来自[fts] 的字符后面的数字匹配的位置。这个(?&lt;=...) 是一个积极的后视,(?=...) 是一个积极的前瞻。

      RegEx live demo

      代码(见演示here):

      string input = "f20s30t";
      string pattern = @"(?<=[fts])(?=\d+[fts])";
      
      string[] substrings = Regex.Split(input, pattern);
      foreach (string match in substrings)
      {
          Console.WriteLine("{0}", match);
      }
      

      输出:

      f
      20s
      30t
      

      【讨论】:

        猜你喜欢
        • 2015-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-18
        • 2016-03-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多