簡體   English   中英

正則表達式-返回匹配的上一個和下一個單詞

[英]Regex - Return previous AND next word from match

我目前有兩個單獨的正則表達式模式來查找目標詞+下一個詞和目標詞+上一個詞:

string text = "Here is a test MYWORD statement for MYWORD regex";
string pattern = "(\\bMYWORD\\s)(\\w+)"; //MYWORD statement; MYWORD regex
string pattern = "(\\w+)(\\s\\bMYWORD)"; //test MYWORD; for MYWORD

正則表達式是否提供了一種優雅的方法來將上述兩種模式結合在一起以用於單個調用?

謝謝

編輯:非常感謝m.buettner和Qtax的出色解釋和示例-非常有用!

我嘗試了提供的一些示例,並且這些示例在所需的上下文中與“ MYWORD”匹配,但也許我不夠清楚:我試圖返回上面注釋的所有短語,即:

Matches(pattern)應該返回以下所有字符串:

'MYWORD statement'
'MYWORD regex'
'test MYWORD'
'for MYWORD'

抱歉,如果我的原始問題解釋得不夠好!

提前進行匹配:

string pattern = @"\b(?=(\w+\s+MYWORD|MYWORD\s+\w+)\b)";

string[] result = Regex.Matches(text, pattern)
                       .Cast<Match>()
                       .Select(match => match.Groups[1].Value)
                       .ToArray();

該正則表達式匹配時不消耗任何字符,這使得重疊匹配成為可能。 您不必擔心無限循環,因為正則表達式引擎在開始尋找下一個匹配項之前會自動向前沖一個位置。 捕獲組仍然可以正常工作。

如果您需要像提到的其他響應者一樣處理字符串開頭和結尾的匹配項,則應這樣做:

string pattern = @"\b(?=((?:^|\w+\s+)MYWORD|MYWORD(?:\s+\w+|$))\b)";

更新:一位評論者詢問如何在不包含目標詞的情況下捕獲前面和后面的詞。 答案很簡單,但並不明顯:

string pattern = @"\b(?=((\w+)\s+MYWORD|MYWORD\s+(\w+))\b)";

string[] result = Regex.Matches(text, pattern)
                       .Cast<Match>()
                       .Select(match => match.Groups[2].Value + match.Groups[3].Value)
                       .ToArray();

簡單的部分是為單個單詞添加捕獲組。 不太明顯的部分是在.NET中意識到,如果捕獲組不參與匹配,並且您訪問其Value屬性,則會得到一個空字符串。 我們知道兩個小組中只有一個會參加每場比賽。 我們不需要知道它是哪一個,我們只需要它的價值。 串接字符串值可以提供所需的確切信息。

但它會變得更好:

string[] result = Regex.Matches(text, pattern)
                       .Cast<Match>()
                       .Select(match => match.Result("$2$3"))
                       .ToArray();

Result()方法並沒有得到太多使用,因為.NET的Regex API的其余部分都經過了精心設計,但是當它有用時,那就太好了!

首先,一些建議:使用逐字字符串。 它們使轉義變得更好處理:

string pattern = @"(\bMYWORD\s)(\w+)"; //MYWORD statement; MYWORD regex
string pattern = @"(\w+)(\s\bMYWORD)"; //test MYWORD; for MYWORD

請注意,您的第二個模式在錯誤的結尾處有單詞邊界:

string pattern = @"(\w+)(\sMYWORD\b)"; //test MYWORD; for MYWORD

現在,幼稚的方法就是這樣:

string pattern = @"(\w+)\s(MYWORD)\s(\w+)";

這有一些問題。 首先,它要求兩個詞都存在,因此,如果MYWORD出現在字符串的一端,則不會有任何匹配。 這可以通過允許使用錨而不是單詞來解決:

string pattern = @"(?:(\w+)\s|^)(MYWORD)(?:\s(\w+)|$)";

現在剩下一個問題了。 比賽不能重疊。 如果您具有abc MYWORD def MYWORD ghi ,則第二個MYWORD將不匹配。 您可以使用環顧四周方法,通過排除匹配項中的周圍單詞來解決此問題:

string pattern = @"(?<=(\w+)\s|^)(MYWORD)(?=\s(\w+)|$)";

如果要允許匹配,既不是在柱的端部也沒有相鄰字(如foo. MYWORD bar ,其中. “塊關”前一個字)。 只需將環顧四周設為可選即可。 如果它們可以匹配,則將它們包括在內,否則,不會導致模式失敗:

string pattern = @"(?<=(\w+)\s)?(MYWORD)(?=\s(\w+))?";

工作演示。

對於您的示例,可以使用一些簡單的方法:

(\w+)\sMYWORD\s(\w+)

但這要求MYWORD兩面都有字。

如果某邊可能沒有任何單詞,可以將其設為可選,例如:

(?:(\w+)\s)?\bMYWORD\b(?:\s(\w+))?

但這將與沒有單詞的MYWORD相匹配。

如果要匹配一個至少包含一個單詞的MYWORD ,可以使用:

(?:(\w+)\sMYWORD\b(?:\s(\w+))?|\bMYWORD\s(\w+))

在這里,右邊的單詞會在第2組或第3組中。

暫無
暫無

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

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