2013-10-06 46 views
2

我有一些想法如何使用正則表達式的方法與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

+0

你谷歌?關閉我的頭頂部,它是'\ 1'或'\ k ' –

+0

我編輯了您的標題。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 –

+0

http://www.regular-expressions.info/named.html –

回答

1

在這種情況下,我可能會使用Regex.replace的overload,需要一個MatchEvaluator。這允許你傳遞一個帶有匹配表達式並返回替換字符串的函數。

下面是一個使用該示例的示例,它將匹配您的所有示例。我還將你的字符串嵌入到文件名中,以顯示它們在文件名中的替換方式(這似乎是你的目標)。

我在這裏爲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 
+0

這看起來像我所需要的(不是說我明白它是如何工作的),但是 - 我在哪裏堅持季節和EP之間的「x」......所以輸出替換爲:「 S01xE01「? – Kairan

+0

已更新,以便在輸出中添加x –

+0

好的非常感謝,這真的爲我節省了很多循環,而且還有瘋狂的邏輯! – Kairan

1

string.replace(pattern, replacement)方法採用匹配給定的模式與給定替換替換它們的字符串的所有部分,然後返回一個新字符串結果。

在你的情況,你需要匹配部分的一部分,在更換使用它們。要做到這一點,你可以使用組,你可以在模式中使用圓括號()創建一個組。 Groups允許你捕獲匹配字符串的一部分,然後在替換中引用它們。

例如,如果你想改變"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引用的是組在更換方式。

+0

感謝您的例子! – Kairan

+0

不客氣;) – carrizo

0

你可以嘗試這樣的事情:

string [email protected]"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(); 

});