正则表达式匹配整数

本文关键字:整数 正则表达式 | 更新日期: 2023-09-27 18:05:17

我输入的字符串是:

"Monday 11:30am,11 v 2,3 v 4"

我需要替换:

  • 11Hurricanes
  • 2Team abc
  • 3 with Vipers
  • 4 with Dodgers
  • 1 with Frozen Rope

等....

但是我不想在11中替换1两次。

我显然不懂正则表达式。但是我尝试了这样做:

string text = File.ReadAllText(CSVpath);
text = Regex.Replace(text,
                     string.Format(@"[{0} v]", CurrentCode),
                     string.Format(@"{0} v", TeamName));
text = Regex.Replace(text,
                     string.Format(@"[v {0}]", CurrentCode),
                     string.Format(@"v {0}", TeamName));
根据上面的输入字符串,输出将是:
"Monday 11:30am,Hurricanes v Team abc,Vipers v Dodgers"

正则表达式匹配整数

试试这个regex:

var subject = "Monday 11:30am,11 v 2,3 v 4,5 v 6";
var replaced = Regex.Replace(subject,@"('d+)'s*v's*('d+)","Team$1 with Team$2");

模式分割:

  • ('d+)捕获数字序列并保存在group1
  • 's*v's*检查v字符包装器两边的零或多个空格。
  • ('d+)捕获数字序列并保存在group2
替换:

$1将第一组替换为Team和第一组的匹配。因此,将11替换为Team11,然后将字面量withTeam相加,并将$2附加在group2的匹配项上。

下面是Regex101的演示

这应该能奏效:'d{1,2}(注意末尾的空字符!)

从http://msdn.microsoft.com/en-us/library/20bw873z(v=vs.110).aspx,它似乎主要与其他语言中的regex语法一致,您可以使用"'d+"来匹配一个或多个十进制数字。

我没有为你构建整个正确的正则表达式,因为你的问题只是关于匹配给定的单一模式(11而不是1)。

这是我的版本:

/(('d+)('b)(?![:]))/g

将作为:

string text = "Monday 11:30am,11 v 2,3 v 4,5 v 6";
var result = Regex.Replace(text, @"(('d+)('b)(?![:]))", "Team$1");
<<p> 在线演示/strong>

'd+ 将捕获尽可能多的数字。 ('b)(?![:]) 通过查找:排除与时间相关联的数字。
('b) 是必需的,因为+的贪心行为。为了确保forward计算整数'b是必需的。

或者根据你的编辑:

string text = "Monday 11:30am,11 v 2,3 v 4,5 v 6";
var result = Regex.Replace(text, @"(('b)(['d]+)('b)(?![:]))", new MatchEvaluator(
delegate(Match m)
{
    return "Team" + m.Value;   /*take value and find the proper team;*/
} ));

你最初的问题读起来好像你想要固定的"Teamnn"格式的输出,但是你的编辑显著地改变了这一点,这样你就想用球队的名字来代替。

首先要做的是定义从队号到队名的查找。我在这里使用了一个"平凡的"1类的简单数组,但是您可以选择任何东西来存储它们,如果数字足够大,甚至可以选择数据库,尽管我怀疑这里的情况是否如此。重要的是它是一个查找表。

class Team
{
    public string Id { get; set; }
    public string Name { get; set; }
}
static Team[] teams = { 
    new Team { Id = "11", Name = "Hurricanes" },
    new Team { Id = "2",  Name = "Team abc" },
    new Team { Id = "3",  Name = "Vipers" },
    new Team { Id = "4",  Name = "Dodgers" },
    new Team { Id = "1",  Name = "Frozen Rope" },
};

现在定义模式匹配。正则表达式

Regex regex = new Regex(@"('d+)'s*v's*('d+)");

将匹配:

  • ('d+) -一个数字序列,并捕获它以替换后面的
  • 's* -可能有空格
  • v -字母v
  • 's* -可能有更多的空间
  • ('d+) -另一个数字序列,并捕获它以替换后面的

注意,两个数字序列——球队号码——将被捕获。由于。net中的正则表达式的工作方式,此fixture的整个字符串将被捕获为组0,第一个队号将是组1,第二个队号将是组2。

public string Test()
{
    string text = "Monday 11:30am,11 v 2,3 v 4";
    foreach (Match match in regex.Matches(text))
    {
        // For the first team in the fixture:
        string team1Id = match.Groups[1].Value; // get the id from the text
        Team team1 = teams.FirstOrDefault(t => t.Id == team1Id); // look it up
        string team1Name = team1.Name; // get the team name
        // For the second team in the fixture:
        string team2Id = match.Groups[2].Value; // get the id from the text
        Team team2 = teams.FirstOrDefault(t => t.Id == team2Id); // look it up
        string team2Name = team2.Name; // get the team name
        // Replace the whole matched string (with numbers)...
        string fixtureWithNumbers = match.Groups[0].Value;
        // ... with the equivalent with team names.
        string fixtureWithNames = team1Name + " v " + team2Name;
        text = text.Replace(fixtureWithNumbers, fixtureWithNames);
    }
    return text;
}

这是手写的。当然,你可以把它缩小一点,像这样:

public string Test2(string text)
{
    foreach (Match m in Regex.Matches(text, @"('d+)'s*v's*('d+)"))
    {
        text = text.Replace(match.Groups[0].Value,
                            teams.FirstOrDefault(t => t.Id == m.Groups[1].Value)
                                 .Name +
                            " v " +
                            teams.FirstOrDefault(t => t.Id == m.Groups[2].Value)
                                 .Name);
    }
    return text;
}

虽然没有真正的好处,而且可能以一点可读性和可维护性为代价,但这些商品往往被低估了。

另一种方法是替换foreach循环,并通过MatchEvaluatorRegex类中进行循环。(我要感谢Dalorzo提出的这个方法)。为此,我将正则表达式更改为((?<T>'d+)(?='s*v))|((?<=v's*)(?<T>'d+)):

  • (?<T>'d+) -一个数字序列,并捕获它作为命名项(T)以替换后面的
  • (?='s*v) -后面跟着一些(或没有)空格和字母v
  • | -or-
  • (?<=v's*) -前面有一个字母v,后面有一些空白
  • (?<T>'d+) -一个数字序列,并捕获它作为命名项(T)以替换后面的

前向和后向表达式假设名称或日期永远不会以字母v结束(在英语中是这样,至少在一些其他语言中可能是这样,但不一定在所有语言中都是这样),但同时允许在团队号码之间存在大于v的变量空白。如果空白是固定的,那么就可以用来改进字符串的前向和后向。

这里的另一个变化是,我从之前创建的数组中创建了一个Dictionary,只有当团队数量变得相对较大时才会产生明显的影响。可见的效果是一个简单的字典查找,而不是对每个团队的数组进行线性扫描。

结果代码看起来像这样:
static Dictionary<string, string> teamDb =
    teams.ToDictionary(t => t.Id, t => t.Name);
public static void Test3(string text)
{
    var result = Regex.Replace(text,
                                @"((?<T>'d+)(?='s*v))|((?<=v's*)(?<T>'d+))",
                                new MatchEvaluator(
                                    m => teamDb[m.Groups["T"].Value]
                                ));
    Console.WriteLine("Test3: {0}", result);
}

在这三种情况下,如果输入字符串包含一个没有出现在查找表中的球队编号,代码仍然有一个未解决的问题(当试图获得Name时,程序将因NullReferenceException而崩溃),但是解决这个问题需要决定在输出字符串中放入什么,如果发生这种情况。

,
1没有微不足道的程序