如何使用正则表达式替换字符串

本文关键字:字符串 替换 正则表达式 何使用 | 更新日期: 2023-09-27 18:34:08

我有一些想法,如何在string.replace 方法中使用正则表达式来"匹配"值,但没有真正如何操作它们。 我正在尝试通过在文件名中找到以下常见模式并用更标准化的命名约定替换它们来重命名文件。

这是我试图替换的示例:

"1x01"01x01"'"101'"S01E"S01 E"S1E"S1 E"S1x">

并将其替换为 S01xE01,其中 S01 代表第 1 季,E01 代表第 1 集,因此数值当然会有所不同......我的想法是正则表达式,但在浏览下一个之后,我不会找到足够具体的例子来帮助我。

我被卡住的部分原因是因为即使找到匹配的表达式,我也不知道如何进行替换。 例如,如果我做类似 string.replace("S''d*E''d*","我放在这里什么?"(。

有没有一个简单的正则表达式可以完成这项任务?

编辑:我一直在审查我看了正则表达式教程和 30 分钟正则表达式教程

如何使用正则表达式替换字符串

在这种情况下,我可能会使用Regex.place的重载,它需要一个MatchEvaluator。 这允许您传递一个函数,该函数采用 Match 表达式并返回替换字符串。

下面是一个使用它的示例,它将匹配您的所有示例。 我还将您的字符串嵌入到文件名中,以显示如何在文件名中替换它们(这似乎是您的目标(。

我在这里为 MatchEvaluator 使用了 lambda 表达式。 如果你想要更复杂的逻辑,你可以在你的类上使用一个方法

我使用了两个正则表达式:一个用于匹配唯一的数字大小写,另一个用于匹配其他所有内容。 我经常发现使用多个简单的正则表达式比尝试使用一个复杂的正则表达式更易于维护。

编辑:更新为使用正则表达式的优先级列表进行尝试。 在列表中找到第一个匹配项后,它将停止检查

您必须确定要以什么顺序使用哪些规则(正则表达式(来适合您的数据。

string[] filenames = {
"1000 Ways to Die S01E01 Life Will Kill You",
"somefile1x01description.ext",
"sometext01x01description.ext",
"sometext101description.ext",
"sometextS01Edescription.ext",
"sometextS01 Edescription.ext",
"sometextS1Edescription.ext",
"sometextS1 Edescription.ext",
"sometextS1xdescription.ext",
"24 S01xE01 12 AM"
};
string [] res = {
    @"[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})", // Handles the cases where you have a delimiter and a digit on both sides, optional S
    @"[sS](?<season>'d{1,2})[ xXeE]+(?<episode>'d{0,2})", // Handles the cases where you have a delimiter, a required S, but optional episode number
    @"(?<season>'d{1,2})(?<episode>'d{2})"  // Handles the case where you just have a 3 or 4 digit number
};
MatchEvaluator reFunc = match => // Given a Regex Match object
// An expression that returns the replacement string
"S" + // Start with the S
match.Groups["season"].Value // get the season group
.PadLeft(2,'0') + // zero pad it
"xE" + // Add the E
(match.Groups["episode"].Value.Length > 0 ? // Is there an episode number?
match.Groups["episode"].Value.PadLeft(2,'0') : // If so, zero pad it
"01" // Otherwise assume episode 01
); // End replacement expression
foreach(string name in filenames)
{
    Console.WriteLine("Orig: {0}",name);
    string replaced = name;
    foreach (string re in res)
    {
        Console.WriteLine("Trying:" + re);
        if(Regex.IsMatch(name,re))
        {
            Console.WriteLine("Matched");
            replaced = Regex.Replace(name,re,reFunc);
            break;
        }
    }
    Console.WriteLine("Replaced: {0}'n'n",replaced);
}

输出:

Orig: 1000 Ways to Die S01E01 Life Will Kill You
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Matched
Replaced: 1000 Ways to Die S01xE01 Life Will Kill You

Orig: somefile1x01description.ext
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Matched
Replaced: somefileS01xE01description.ext

Orig: sometext01x01description.ext
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Matched
Replaced: sometextS01xE01description.ext

Orig: sometext101description.ext
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Trying:[sS](?<season>'d{1,2})[ xXeE]+(?<episode>'d{0,2})
Trying:(?<season>'d{1,2})(?<episode>'d{2})
Matched
Replaced: sometextS01xE01description.ext

Orig: sometextS01Edescription.ext
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Trying:[sS](?<season>'d{1,2})[ xXeE]+(?<episode>'d{0,2})
Matched
Replaced: sometextS01xE01description.ext

Orig: sometextS01 Edescription.ext
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Trying:[sS](?<season>'d{1,2})[ xXeE]+(?<episode>'d{0,2})
Matched
Replaced: sometextS01xE01description.ext

Orig: sometextS1Edescription.ext
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Trying:[sS](?<season>'d{1,2})[ xXeE]+(?<episode>'d{0,2})
Matched
Replaced: sometextS01xE01description.ext

Orig: sometextS1 Edescription.ext
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Trying:[sS](?<season>'d{1,2})[ xXeE]+(?<episode>'d{0,2})
Matched
Replaced: sometextS01xE01description.ext

Orig: sometextS1xdescription.ext
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Trying:[sS](?<season>'d{1,2})[ xXeE]+(?<episode>'d{0,2})
Matched
Replaced: sometextS01xE01description.ext

Orig: 24 S01xE01 12 AM
Trying:[sS]?(?<season>'d{1,2})[ xXeE]+(?<episode>'d{1,2})
Matched
Replaced: 24 S01xE01 12 AM

string.replace(pattern, replacement) 方法获取与给定模式匹配的字符串的所有部分,并将它们替换为给定的替换,然后返回一个包含结果的新字符串。

在您的情况下,您需要部分匹配的部分才能在替换中使用它们。为此,您可以使用组,在模式内使用括号()创建一个组。组允许您捕获匹配字符串的各个部分,然后在替换中引用它们。

例如,如果要将"S01E02"更改为Season-01-Episode-02则需要具有两组的模式,例如"S('d+)E('d+)"。然后你可以做这样的事情:

"blabla S01E02 asdasd S01E05 erterert S04E07".replace("Season-$1-Episode-$2")

结果将是这样的:

"blabla Season-01-Episode-02 asdasd Season-01-Episode-05 erterert Season-04-Episode-07"
$

1 和 $2 是您在替换中引用组的方式。

你可以尝试这样的事情:

string s=@"Dr Who 101";
s = Regex.Replace(s,
    @"(?i)S?(?<!'d)(?<sa>'d{1,2})x ?E?(?<ep>'d{2})?(?!'d)",
    delegate(Match match) {
    return "S"
         + ((match.Groups["sa"].ToString().Length<2)?"0":"")
         + match.Groups["sa"].ToString()
         + "xE" + match.Groups["ep"].ToString();
});