2012-05-02 115 views
1

在Java程序界定,我想找出這些子給定的字符串中所有出現:$$或$ \ d(符號「$」後跟一個整數)。匹配字符串中的某些關鍵字不是由某些字符

我的問題開始時,我增加了一個額外的限制,指出只有在匹配字符串不是由某些字符序列限制的子串的一部分發生匹配。

例如,我想忽略匹配,如果它們是由「/ {」和「/}」所包圍的字符串的一部分。

以下示例將帶出所有出現的$$或$ \ d,但不考慮忽略匹配的附加約束(如果它位於「/ {」和「/}」內部)。

public static final String PARAMETERS_PREFIX = "$"; 
public static final String ALL_PARAMS_SUFFIX = "$"; 
public static final String BEGIN_JAVA_EXPRESSION = "/{"; 
public static final String END_JAVA_EXPRESSION = "/}"; 
... 
String test = "$1 xxx $$ " //$1 and $$ are matches 
    + BEGIN_JAVA_EXPRESSION + "xxx $2 xxx" + END_JAVA_EXPRESSION; //$2 SHOULD NOT be a match 
Set<String> symbolsSet = new LinkedHashSet<String>(); 
Pattern pattern = Pattern.compile(Pattern.quote(PARAMETERS_PREFIX)+"(\\d+|"+Pattern.quote(ALL_PARAMS_SUFFIX)+")"); 
Matcher findingMatcher = pattern.matcher(test); 
while(findingMatcher.find()) { 
    String match = findingMatcher.group(); 
    symbolsSet.add(match); 
} 
return new ArrayList<String>(symbolsSet); 

除了發現不能確定的子部分的關鍵字,我希望能夠通過一定值後只更換這些關鍵字。 然後,在進行匹配之前刪除分隔字符之間的所有內容的選項可能無濟於事,因爲之後我需要能夠獲取原始字符串,並將匹配的標記替換爲某些值,並且分隔區域內的標記應該留下未經修改。 這應該很容易,如果我找到了正確的正則表達式。

是否有人可以給我一個關於如何編寫正確的正則表達式這個問題的暗示?

回答

2

允許使用多於1個正則表達式嗎?它可能不那麼性感,但你可以用3個正則表達式很容易做到這一點。 (這些都不是實際的正則表達式的) 1.爲了得到你正在尋找的字符串($$ | $ {NUM}) 2.對於 '/ {' 3.對於 '/}'

它應該是相當容易的無效面積在2和3。然後,您可以使用這些跨度,以消除1

+0

+1謝謝您的回答@ControlAltDel。然而,我忘了在問題中說,以後我需要用其他值替換匹配的字符串(我剛剛更新了它)。我認爲只有一個正則表達式是理想的。不知道如何找到我使用多個正則表達式的關鍵字。 – Sergio

+0

我沒有看到如何找到使用我建議的3個正則表達式的位置比使用1個正則表達式更復雜。但你知道你的問題比我更好... – ControlAltDel

+0

我想說的是,我正在尋找一個正則表達式,我可以使用它們來查找匹配,以及之後替換某些值的標記。所以我可以做一些像test.replaceAll(「killerRegex」,「newValue」)。 「killerRegex」將忽略周圍區域的匹配。 – Sergio

0

結果匹配我不是正則表達式的專家,所以我會嘗試使用計數器的數量{ }。 {平均值+1 }表示-1 如果計數器爲0,那麼使用正則表達式是安全的。如果計數器不是0,那麼嘗試正則表達式就沒用了。我相信這是一個只有RegExp的解決方案,但我再次不是它的主人。

1

我建議爲此使用多個正則表達式。試圖一次完成 - 雖然誘人 - 似乎相當混亂。

  1. 取下字符串你的「Java表達式」:/{.*?/}
  2. 運行您對得到的字符串匹配:\$(?:\d+)?

注:我是第一個表達式懶惰,所以它假定任何/{的出現將最終跟隨/}並且沒有嵌套。

0

我不確定你可以用一個正則表達式來做到這一點。如果沒有一個能提供這種終極正則表達式我做了一個小的解決方法:

public static final String PARAMETERS_PREFIX = "$"; 
public static final String ALL_PARAMS_SUFFIX = "$"; 
public static final String BEGIN_JAVA_EXPRESSION = "/{"; 
public static final String END_JAVA_EXPRESSION = "/}"; 

    String test = "$1 xxx $$ " //$1 and $$ are matches 
    + BEGIN_JAVA_EXPRESSION + "xxx $2 xxx" + END_JAVA_EXPRESSION; //$2 SHOULD NOT be a match 
    Set<String> symbolsSet = new LinkedHashSet<String>(); 
    Pattern pattern = Pattern.compile(Pattern.quote(PARAMETERS_PREFIX)+"(\\d+|"+Pattern.quote(ALL_PARAMS_SUFFIX)+")"); 
    Matcher findingMatcher = pattern.matcher(test); 
    while(findingMatcher.find()) { 
     String match = findingMatcher.group(0); 
     int idx= findingMatcher.start(); 
     int bexIdx = test.lastIndexOf(BEGIN_JAVA_EXPRESSION,idx); 
     if(bexIdx!=-1){ 
      int endIdx = test.indexOf(END_JAVA_EXPRESSION,bexIdx); 
      if(endIdx<idx){ 
       symbolsSet.add(match); 
      } 
     } 
     else{ 
      symbolsSet.add(match); 
     } 
    } 
1

,你需要可使用此正則表達式來實現第一部分:

(?<!/{)\($[$|\d])(?!}/) 

因此,運行此之後,你會得到所有的小組比賽 - 從現在開始,您可以通過評估小組中的比賽並找到合適的替代品,讓Java來完成艱苦的工作。

你應該能夠使用反向引用以某種方式做替換位,但我想你可以弄明白。

UPDATE:

(?<!/{) - 這是一個負回顧後 - 它說:從當前位置斷言,以前的字符不/{。如果這個計算結果爲true,那麼/ {的匹配被丟棄並且真正的匹配開始。 Lookahead/lookbehind是不參與比賽的零寬度斷言。

(?!}/) - 類似地,但在另一個方向上 - 從當前位置斷言下列字符不是} /。這些也不參加比賽。如果滿足這些條件,那麼實際上,您的匹配仍然只是斷言中的文本,即$$或$ \ d。

BTW:它可能是你需要逃避一些字符 - 那些我記得是{和$以外的字符類

(?<!/\{)\(\$[$|\d])(?!}/) 

還看到: How to escape text for regular expression in Java

+0

@Sergio - 忘了解釋,看看更新。 –

+0

謝謝@Joanna。前兩個括號之間的「\」是錯誤的?我不明白你在逃避什麼。 – Sergio

+0

@Sergio - 在第一個括號中,我用'\'來轉義'{',否則可能被解釋爲這個結構的一部分,你可以用它來指定字符'{2,3}的出現次數「至少兩次,最多三次 –

0

您可以使用一個模式與Lookaround

(?<!\\{[^\\}]{0,100})\\$(\\d|\\$)(?![^\\{]*\\})

  • (?<!\\{[^\\}]{0,100})組用於限制前驅值

    這使用否定向後看:{?<!X},其中X是不能在主表達式之前的正則表達式。在Java中,如果沒有明顯的最大長度,你不能使用負面的揹負,那麼你不能使用\\{.*。您可以使用Integer.MAX_VALUE,或testString.length()。另一件事:你必須檢查你是否在開始符號之前找到結束符號。因此,該表達式是[^\\}]而不是.

  • \\$(\\d|\\$)主要羣體尋求

    通常在這裏。

  • (?![^\\{]*\\})組用於限制後值

    這種使用負先行:{?!X},其中X是一個正則表達式表達不能成功主要表達。在這裏,你可以使用無固定長度。再次,你必須檢查你是否找到了子串的開始符號。然後,您使用[^\\{]*而不是.*

但是,添加更多的約束會在您的正則表達式中增加更多的複雜性。


字符串測試模式:"$1 xx3x $$ /{xxx $2 xxx/} $4"