65.9K
CodeProject 正在变化。 阅读更多。
Home

正则表达式匹配以特定数字开头的版本号

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2022年8月20日

CPOL

4分钟阅读

viewsIcon

12440

如何在具有特定匹配要求的正则表达式中使用插入符号 (^) 的示例

引言

我最近在工作中遇到了这样一个需求:可以访问一个充满配置文件的文件夹。

任务是修复一个替换文件版本号的脚本。

问题是脚本没有进行正确的替换,从而弄乱了依赖于配置文件的系统的运行。

一些包含但并非以特定数字开头的版本号的中间部分被替换了,而这并非预期的功能。

在本文中,我们将探讨如何重新编写脚本以正确识别需要更新的版本号。

背景

名为PostSharp的NuGet包非常有用。但是,其作者经常更新它。我们组织有一个要求,所有依赖于PostSharp NuGet包的软件必须始终使用最新版本。

截至撰写本文时,PostSharp的版本号为6.10.15。我有很多packages.config文件需要更新其中的版本号,这样我就可以在命令行上执行nuget restore来更新包。

因此,我想到了在LINQPad中编写一个C#脚本,该脚本将迭代root目录中的packages.config文件和*.csproj文件,并将文件中的版本号替换为从NuGet网站抓取的最新版本。

正则表达式(简称Regex)的困境

手头的任务

我试图匹配一个版本号(以便在各种config文件中替换它)。

我想匹配的版本号

  • 始终由三个数字组成,包含0-99,用点号分隔
  • 第一个数字始终是6

例如,6.10.14是一个示例版本号。

当前代码

为了进行替换,我使用了以下代码

public static class Update
{
    private static string PostSharpVersionToLatest(string contents)
    {
        var result = string.Empty;

        if (string.IsNullOrWhiteSpace(contents)) return result;

        try
        {
            result =
                Regex.Replace(
                    contents,
                    @"6\.\d+\.\d+",
                    LATEST_POSTSHARP_VERSION
                );
            result =
                Regex.Replace(
                    result,
                    @"6\.\d+\.\d+\-rc",
                    LATEST_POSTSHARP_VERSION
                );
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);

            result = string.Empty;
        }

        return result;
    }
}

用于查找和替换版本号的正则表达式是6\.\d+\.\d+

当时看起来像是正确的正则表达式。

但是,在我搜索和进行替换的文本文件中还有其他版本号,例如16.301.204959.29等等。我使用的模式也匹配这些,而这并非我想要的结果。我只希望开头是6.的匹配,而不是开头是16.等的版本号也匹配。

不断发生的问题是,较长版本号中的6.301.204959文本也被匹配并替换,这会导致packages.config文件损坏。

Regex Hero来救援

有一个非常方便的实用程序——我推荐你获取——叫做Regex Hero

我将使用它来找出我的正则表达式有什么问题。显示使用正则表达式6\.\d+\.\d+匹配目标字符串6.10.14的Regex Hero窗口在**图1**中可见。

图1. Regex Hero窗口显示目标字符串6.10.14被正则表达式6\.\d+\.\d+匹配。

我们的模式似乎运行良好。但是,假设较长的版本号16.301.204959.29也存在于我们正在进行查找和替换操作的文本文件中。

我们将它放入Regex Hero的**目标字符串**框中,使用**正则表达式**字段的相同值,并获得如**图2**所示的结果。

图2. Regex Hero显示与目标字符串16.301.204959.29的部分匹配。

可以想象,如果我们尝试进行文本替换操作,而我们只想定位明确以6开头而不是1636等的版本号,这可能会导致问题。

使用脱字符号(^)

我知道我可以在正则表达式的开头使用脱字符号 (^)。根据这篇博文

引用

你可以在正则表达式的开头使用脱字符号(^)来指示匹配必须出现在被搜索文本的开头。

我的想法是尝试以下正则表达式:^6\.\d+\.\d+。正如在Regex Hero中看到的,版本号16.301.204959.29没有匹配,如图3所示。

图3. Regex Hero使用正则表达式^6\.\d+\.\d+显示版本号16.301.204959.29没有匹配。

让我用我的新正则表达式尝试示例版本号6.10.14,如图4所示。

图4. Regex Hero使用正则表达式^6\.\d+\.\d+显示对值6.10.14的正向匹配。

结论

我们可以看到,通过在正则表达式的开头使用脱字符号^,可以解决创建仅匹配以特定数字开头的值的正则表达式的問題。

历史

  • 2022年8月20日:初始版本
© . All rights reserved.