[英]Regex to match whole numbers
我輸入了以下字符串:
"Monday 11:30am,11 v 2,3 v 4"
我需要更換:
11
與Hurricanes
2
與Team abc
3
帶Vipers
4
與Dodgers
1
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"
試試這個正則表達式:
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替換,然后加上一個帶$2
的文字with
而一個帶$2
的Team
文字附加group2的匹配項。
這應該可以解決問題: \\d{1,2}
(請注意末尾的空字符!)
從http://msdn.microsoft.com/zh-cn/library/20bw873z(v = vs.110).aspx (似乎與其他語言的正則表達式語法基本一致)中,可以使用“ \\ d +”匹配一個或多個十進制數字。
我沒有為您構造整個正確的正則表達式,因為您的問題只是關於匹配給定的單個模式(11而不是1)。
最初的問題"Teamnn"
要為輸出使用"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中正則表達式的工作方式,此固定裝置的整個字符串將被捕獲為組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
循環,並通過MatchEvaluator
在Regex
類中完成循環。 (我感謝Dalorzo提出了這種方法)。 為此,我將正則表達式更改為((?<T>\\d+)(?=\\s*v))|((?<=v\\s*)(?<T>\\d+))
:
(?<T>\\d+)
-一個數字序列,並將其捕獲為命名項(T),以便以后替換 (?=\\s*v)
-后面跟一些(或沒有)空格和字母v
|
-要么- (?<=v\\s*)
-開頭是字母v
后跟一些(或沒有)空格 (?<T>\\d+)
-一個數字序列,並將其捕獲為命名項(T),以便以后替換 前瞻性和后向表達式假定名稱或日期永遠不會以字母v結尾(英語為true,可能至少是幾種其他語言,但不一定是全部),但同時也允許使用可變空格團隊編號之間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沒有瑣碎的程序。
這是我的版本:
/((\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");
\\d+
將捕獲盡可能多的數字。
(\\b)(?![:])
通過搜索:
排除與時間相關的數字。
由於存在+
的貪婪行為,因此需要(\\b)
。 為了確保前瞻評估整數\\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;*/
} ));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.