簡體   English   中英

是否有可能有重疊的正則表達式匹配?

[英]Is it possible to have overlapping regex matches?

以這個數據為例:

ID: JK546|Guitar: 0|Piano: 1|Violin: 0|Expiry: Aug14,2021

我想知道是否可以創建一個將返回這組匹配項的正則表達式

ID: JK546|Guitar: 0|Expiry: Aug14,2021
ID: JK546|Piano: 1|Expiry: Aug14,2021
ID: JK546|Violin: 0|Expiry: Aug14,2021

我確實嘗試在下面創建一個:

ID: (?<id>\w+).*\|(?<instrument>\w+):\s(?<count>\d).*Expiry:\s(?<expiry>[\w\d]+)

但它只返回了一個小提琴樂器。 我非常感謝您對此的見解。

我不會使用正則表達式。 特別是由於字符串ID: JK546|Guitar: 0|Expiry: Aug14,2021沒有出現在字符串ID: JK546|Guitar: 0|Piano: 1|Violin: 0|Expiry: Aug14,2021中,所以嚴格來說它不是匹配,但更多的是替代品。 但是沒有什么好方法可以從所有比賽中獲得所有替補。

所以,我只是將輸入字符串拆分為| .

然后,您想要組成一個由第一個字段、一個中間字段和最后一個字段組成的結果字符串。 對於存在的每個中間字段,您將獲得一個結果。 如果它拆分為 N 個字段,您將獲得 N-2 個結果。 例如:如果它分成 5 個字段,那么您將得到 3 個結果,每個“中間”字段一個。

string input = "ID: JK546|Guitar: 0|Piano: 1|Violin: 0|Expiry: Aug14,2021";
string[] fields = input.Split('|');
for( int i = 1; i < fields.Length - 1; ++i) {
    string result = string.Join("|", fields.First(), fields[i], fields.Last());
    Console.WriteLine(result);
}

output:

ID: JK546|Guitar: 0|Expiry: Aug14,2021
ID: JK546|Piano: 1|Expiry: Aug14,2021
ID: JK546|Violin: 0|Expiry: Aug14,2021

在多個調用中返回多個匹配項的單個正則表達式? 我想知道這是否可能。

我不熟悉如何在 C# 中進行正則表達式處理,但是這個sed命令會做你想做的事。 也許您可以了解它的工作原理並使其適應您的需求:

sed -n ':loop; h; s/^\([^|]*|[^|]*\).*\(|.*\)$/\1\2/p; g; s/^\([^|]*\)|[^|]*\(|.*\)$/\1\2/; t loop'

為簡單起見,我們假設輸入字符串是“A|B|C|D|E”。

它能做什么:

  • -n是告訴sed不要自動打印任何東西的選項(但只有在被告知時才打印,使用p命令)。
  • :loop是一個 label,實際上是一個“goto”。 所以使用while循環結構。
  • h將模式空間保存到保持空間中。 換句話說,復制你的字符串。
  • s/^\([^|]*|[^|]*\).*\(|.*\)$/\1\2/p捕獲前兩個段和最后一個段,並打印結果。 所以“A|B|C|D|E”變成了“A|B|E”(即你想要的第一個輸出)。
  • g將保存的字符串從保持空間恢復到模式空間。 換句話說,檢索您保存的字符串的副本。
  • s/^\([^|]*\)|[^|]*\(|.*\)$/\1\2/捕獲第一段,跳過第二段,然后捕獲 rest。 所以“A|B|C|D|E”變成了“A|C|D|E”。
  • t loop是“goto”命令。 如果最近的替換成功,它會告訴 go 回到循環的開頭。 換句話說,這是循環的結束,也是循環條件的規范。

循環的第二次迭代會將“A|C|D|E”更改為“A|C|E”並打印出來。 然后將“A|C|D|E”更改為“A|D|E”並迭代。 循環的第三次迭代會將“A|D|E”更改為“A|D|E”並打印出來。 (顯然沒有變化,因為正則表達式中間的.*匹配“A|D”和“|E”之間的零長度字符串。)最后的替換將“A|D|E”更改為“A |E”,然后就什么也找不到了。

您可以使用 .NET Groups.Captures屬性來獲取吉他、鋼琴和小提琴的值。

(ID: \w+\|)(\w+: \d+\|)+(Expiry: \w+,\d+)

模式匹配:

  • (ID: \w+\|)捕獲組 1匹配ID: 1+ 單詞字符和|
  • (\w+: \d+\|)+捕獲組 2重復 1+ 次匹配 1+ 個單詞字符: 1+ 個數字|
  • (Expiry: \w+,\d+)捕獲組 3匹配Expiry: 1+ word chars , 1+digits

在此處輸入圖像描述

查看.NET 正則表達式演示| C# 演示

例如

var str = "ID: JK546|Guitar: 0|Piano: 1|Violin: 0|Expiry: Aug14,2021";
string pattern = @"(ID: \w+\|)(\w+: \d+\|)+(Expiry: \w+,\d+)";
Match m = Regex.Match(str, pattern);

foreach(Capture c in  m.Groups[2].Captures) {
    Console.WriteLine(m.Groups[1].Value + c.Value + m.Groups[3].Value);
}

Output

ID: JK546|Guitar: 0|Expiry: Aug14,2021
ID: JK546|Piano: 1|Expiry: Aug14,2021
ID: JK546|Violin: 0|Expiry: Aug14,2021

向后看和向前看應該是可能的:

string foo = @"ID: JK546 | Guitar: 0 | Piano: 1 | Violin: 0 | Expiry: Aug14,2021";

// First look at "Guitar: 0", "Piano: 1" and "Violin: 0". Then look behind "(?<= )" and search for the ID. Then look ahead "(?= )" and search for Expiry.

string pattern = @"(\w+: \d)(?<=(ID: [A-Z0-9]+).*?)(?=.*?(Expiry: \S+))";

foreach (var match in Regex.Matches(foo, pattern))
{
    ....                
}

幸運的是 c# 是少數可以處理可變長度后視的語言之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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