2016-06-21 105 views
1

我使用的系統其中&後跟某個字母或數字表示一種顏色。
可以遵循&有效字符爲[A-Fa-fK-Ok-or0-9]具有優先級的Java正則表達式匹配模式

比如我有串&aThis is a test &bstring that &ehas plenty &4&lof &7colors.

我想在每一個& X拆分,同時保持字符串中的& X
所以我在我的正則表達式
(?=(&[A-Fa-fK-Ok-or0-9]))
這工作完全沒使用正向前查找,輸出爲:

&aThis is a test 
&bstring that 
&ehas plenty 
&4 
&lof 
&7colors.

的問題是,有& X兩個實例旁邊的點對方不應該被拆分,該線應該是&4&lof

有誰知道我可以使用正則表達式是什麼,這樣,當有兩個&彼此相鄰它們是匹配在一起X的。顏色代碼的兩個實例應該優先於單個實例。

+0

那麼爲什麼不在?=(和&[在你的正則表達式中]之間加一個空格? – Tiina

+0

因爲整個想法是讓它們作爲一個整體匹配在一起,而不是單獨的 –

+0

你說「$ a $ b」和「$ a $ b」是一個,所以並不是說正則表達式應該更像「(?=(&[A-Fa-fK-Ok-or0-9]))」, &??那麼你只需要特別注意字符串中的第一個字符,我認爲這是最簡單和直接的方式 – Tiina

回答

1

問題說明

的問題是公知的:你需要標記一個可能包含連續分隔符的字符串需要保留爲結果字符串列表/數組中的單個項目。

劈開環視(S)也不能幫助這裏,因爲未錨定環視測試串內的各位置。如果您的模式匹配字符串中的任何字符,則可以使用\G運算符,但情況並非如此。即使增加一個+量詞 - s0.split("(?=(?:&[A-Fa-fK-Ok-or0-9])+)"would still return &4, &lof as separate tokens因此。

解決方案

使用匹配而不是分裂,並用積木來保持它的可讀性。

String s0 = "This is a text&aThis is a test &bstring that &ehas plenty &4&lof &7colors."; 
String colorRx = "&[A-Fa-fK-Ok-or0-9]"; 
String nonColorRx = "[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*"; 
Pattern pattern = Pattern.compile("(?:" + colorRx + ")+" + nonColorRx + "|" + nonColorRx); 
Matcher m = pattern.matcher(s0); 
List<String> res = new ArrayList<>(); 
while (m.find()){ 
    if (!m.group(0).isEmpty()) res.add(m.group(0)); // Add if non-empty! 
} 
System.out.println(res); 
// => [This is a text, &aThis is a test , &bstring that , &ehas plenty , &4&lof , &7colors.] 

的正則表達式是

(?:&[A-Fa-fK-Ok-or0-9])+[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*|[^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)* 

regex demo here。它實際上是基於你的初始模式:首先,我們匹配所有的顏色代碼(一個或多個序列),然後匹配0個以上不是顏色序列起點的字符(即除顏色代碼以外的所有字符串)。 [^&]*(?:&(?![A-Fa-fK-Ok-or0-9])[^&]*)*子模式是(?s)(?:(?!&[A-Fa-fK-Ok-or0-9]).)*的同義詞,當需要匹配除指定的文本以外的某些文本塊時非常方便,但由於它是資源消耗(尤其是在Java中),所以展開版本更可取。

因此,模式 - (?:" + colorRx + ")+" + nonColorRx + "|" + nonColorRx - 匹配1+ colorRx子模式,隨後可選nonColorRx子模式,OR(|)零個或多個nonColorRx子模式。 .group(0).isEmpy()不允許結果數組中的空字符串。

0

我想:

{

 String line = "&aThis is a test &bstring that &ehas plenty &4&lof &7colors."; 
     String pattern = " &(a-z)*(0-9)*"; 

     String strs[] = line.split(pattern, 0); 
     for (int i=0; i<strs.length; i++){ 
      if (i!=0){ 
       System.out.println("&"+strs[i]); 
      } else { 
       System.out.println(strs[i]); 
      } 
     } 

}

,輸出是: {

&aThis is a test 
&bstring that 
&ehas plenty 
&4&lof 
&7colors. 

}

我們可以添加ŧ他&在所有子字符串的開頭,以獲得您正在尋找的結果。

0

這樣的事情會起作用。

它使用String#split方法並放置有效行成ArrayList(例如colorLines

String mainStr = "&aThis is a test &bstring that &ehas plenty &4&lof &7colors"; 
String [] arr = mainStr.split("&"); 

List<String> colorLines = new ArrayList<String>(); 

String lastColor = ""; 
for (String s : arr) 
{ 
    s = s.trim(); 
    if (s.length() > 0) 
    { 
     if (s.length() == 1) 
     { 
      lastColor += s; 
     } 
     else 
     { 
      colorLines.add(lastColor.length() > 0 ? lastColor + s : s); 
      lastColor = ""; 
     } 
    } 
} 

for (String s : colorLines) 
{ 
    System.out.println(s); 
} 

輸出

aThis is a test 
bstring that 
ehas plenty 
4lof 
7colors