簡體   English   中英

Java regex匹配貪婪數據(可選后綴除外)

[英]Java regex matching greedy data apart from optional suffix

給定一個像

Prefix without commas, remainder with optional suffix (optional suffix)

一次匹配並提取字符串的3部分的最佳Java正則表達式是什么?

  1. 直到第一個逗號的前綴
  2. 余數直到左括號
  3. 括號內的后綴

對於上面的示例,這3個組(用引號引起來)將是

  1. “沒有逗號的前綴”
  2. “剩余的帶有可選后綴”
  3. “(可選的后綴)”

字符串的所有3個部分的長度都是可變的。 “剩余”部分本身可以包含逗號和括號,並且可選的后綴可以以空格開頭,也可以不以空格開頭,然后是左括號,后面是零個或多個字符,然后是右括號,后面是可選空格,然后是行結束。

嘗試類似的東西

([^,]*),(.*)(\s*\(.*\))?

僅產生組1和2,將組3置於組2的末尾。

 ([^,]*),(.*)(\\s*\\(.*\\))? 

失敗的原因是,正則表達式已經以([^,]*),(.*) ,並且不需要檢查(回溯)其余的。

要使其正常工作,請按如下所示更改它(可能有多個選項),這些匹配要么不帶最后一個括號,要么將匹配最后一個括號:

^([^,]*),(.*[^\) ]\s*$) | ([^,]*),(.*)(\s*\(.*\))\s*$

結果( $1 + $3$2 + $4應該合並,如果沒有可選前綴,則填充$1$2 ):

3: Prefix without commas
4:  remainder with optional suffix 
5: (optional suffix)

在這里,我假設您的可選后綴可以出現多次。 閱讀問題的另一種方式是,您希望重復中間部分,即$3包含在$2 您可以按照以下步驟進行操作:

^([^,]*),(.*(?:[^\) ]\s*$ | (\s*\(.*\)\s*$)))

結果:

1: Prefix without commas
2:  remainder with optional suffix (optional suffix)  
3: (optional suffix)  

編輯:在正則表達式上方進行了更新,以使右括號后可以留有空格(這很細微,您需要在負字符類中添加空格),並錨定了正則表達式以加快速度並減少回溯

您可以使用以下正則表達式:

"^([^,]*),([^()]*)(\\s*\\(.*\\))?$"

正則表達式匹配:

  • ^ -字符串的開頭
  • ([^,]*) -(第1組)0個或多個字符,
  • , -文字,
  • ([^()]*) -(第2組)除()以外的0個或更多字符
  • (\\\\s*\\\\(.*\\\\))? -(第3組)可選組(由於?量詞表示前面的子模式出現1或0):
    • \\\\s* -0或多個空格
    • \\\\(.*\\\\) -文字(然后是除換行符以外的盡可能多的字符,直到最后一個)
  • $ -字符串的結尾(如果實際字符串可以更長,則刪除該字符串,而您正在尋找較小的子字符串)。

IDEONE演示

String str = "String prefix without commas, variable length remainder with optional suffix (optional suffix)";
Pattern ptrn = Pattern.compile("^([^,]*),([^()]*)(\\s*\\(.*\\))?$");
Matcher matcher = ptrn.matcher(str);
while (matcher.find()) {
    System.out.println("First group: " + matcher.group(1)
                  + "\nSecond group: " + matcher.group(1) 
                  + (matcher.group(3) != null ? 
                       "\nThrid group: " + matcher.group(3) : ""));

以下正則表達式:

^([^,]*),(.*?)(?:\(([^()]*)\))?\s*$

在組2中使用惰性量詞以確保組3將匹配(如果有任何括號)。 另一方面,組3不允許嵌套的括號,僅在字符串的最后一組括號中強制匹配。

碼:

String text = "String prefix without commas, variable length ())(remainde()r with )optional (suffix (optional suffix)";
Pattern regex = Pattern.compile("^([^,]*),(.*?)(?:[(]([^()]*)[)])?\\s*$");
Matcher m = regex.matcher(text);
if (m.find()) {
    System.out.println("1: " + m.group(1));
    System.out.println("2: " + m.group(2));
    System.out.println("3: " + m.group(3));
}

輸出:

1: String prefix without commas
2:  variable length ())(remainde()r with )optional (suffix 
3: optional suffix

DEMO

暫無
暫無

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

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