如何使用Regex替换String

时间:2013-10-06 00:46:27

标签: c# regex string replace

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

这是我要替换的例子:

" 1x01" " 01x01" " 101" " S01E" " S01 E" " S1E" " S1 E" " S1X"

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

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

是否有一个能够完成此任务的简单正则表达式?

编辑:我一直在审核,我查看了Regex Tutorial30 Minute Regex Tutorial

3 个答案:

答案 0 :(得分:1)

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是您在替换中引用组的方式。

答案 1 :(得分:1)

在这种情况下,我可能会使用带有MatchEvaluator的Regex.replace overload。这允许您传递一个带有Match表达式并返回替换字符串的函数。

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

我在这里为MatchEvaluator使用了lambda表达式。如果您想要更复杂的逻辑,可以use a method on your class

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

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

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

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

答案 2 :(得分:0)

您可以尝试这样的事情:

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();

});