簡體   English   中英

正則表達式匹配整數

[英]Regex to match whole numbers

我輸入了以下字符串:

"Monday 11:30am,11 v 2,3 v 4"

我需要更換:

  • 11Hurricanes
  • 2Team abc
  • 3Vipers
  • 4Dodgers
  • 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而一個帶$2Team文字附加group2的匹配項。

這是Regex101演示

這應該可以解決問題: \\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循環,並通過MatchEvaluatorRegex類中完成循環。 (我感謝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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM