[英]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例如
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.