2017-06-08 62 views
2

我有兩種模式,如下圖所示:如何區分兩個正則表達式,一個是另一個的子串?

  • I型:${<varName>}
  • II型:$${<varName>}

的模式可以發現獨自站立,或字符串中包含多個匹配。我需要找到這些模式的出現,所以我寫了一個查詢來匹配正則表達式進行搜索。但是,問題在於,對於任何Type II模式,它們本身都包含與Type I模式匹配的內容。例如,$${newVar}將被檢測兩次,分別爲$${newVar}${newVar}。我只希望前者被退回。我使用的正則表達式是:

  • I型:\$\{[a-zA-Z0-9]+\}
  • II型:\$\$\{[a-zA-Z0-9]+\}

你可以看到檢測到的字符串here(下圖)的一個例子

enter image description here

請注意,第二次檢測是正確的,而第一次檢測是不需要的。

反正也有修改這些正則表達式來滿足我的需要嗎?或者有其他的選擇嗎?請隨時提出建議。歡迎所有的答案!謝謝你們。

+0

應該不是你的II型是'\ $ \ $ \ {[A-ZA-Z0-9] + \}'?對於類型I,你有沒有'[^ \ $] \ $ \ {[a-zA-Z0-9] + \}'? – AntonH

+0

爲錯字道歉,它是'''\ $ \ $''''。對於你建議的正則表達式,我試過了,它會匹配模式前面的任何字符,例如'''fasdfasd'f $ {var}''''('''''''表示匹配) – mrawesome

+0

你是對的,我忘了它會被包含在捕獲中。它可能需要一個預見,但我不夠好,以提供解決方案。 – AntonH

回答

2

看來你需要找到的 I型和II型模式的出現,所以你應該做的在一次掃描中。

,可以這樣進行:

String input = "adklsfjb$${xxx}dklsjfnsdklj${yyy}"; 

Pattern p = Pattern.compile("(\\$)?\\$\\{([^}]+)}"); 
for (Matcher m = p.matcher(input); m.find();) { 
    if (m.start(1) == -1) { 
     System.out.println("Found Type I match for variable '" + m.group(2) + "'" + 
          " at index " + m.start() + "-" + m.end()); 
    } else { 
     System.out.println("Found Type II match for variable '" + m.group(2) + "'" + 
          " at index " + m.start() + "-" + m.end()); 
    } 
} 

輸出

Found Type II match for variable 'xxx' at index 8-15 
Found Type I match for variable 'yyy' at index 27-33 

UPDATE

如果你想和值替換的模式,你可以使用appendReplacement()appendTail()

例子:

String input = "adklsfjb$${xxx}dklsjfnsdklj${yyy}adljfhjh"; 

Map<String, String> type1 = new HashMap<>(); 
type1.put("xxx", "[type I with x's]"); 
type1.put("yyy", "[type I with y's]"); 

Map<String, String> type2 = new HashMap<>(); 
type2.put("xxx", "{TYPE 2 WITH x's}"); 
type2.put("yyy", "{TYPE 2 WITH y's}"); 

StringBuffer buf = new StringBuffer(); 
Matcher m = Pattern.compile("(\\$)?\\$\\{([^}]+)}").matcher(input); 
while (m.find()) { 
    String var = m.group(2); 
    String repl = (m.start(1) == -1 ? type1.get(var) : type2.get(var)); 
    if (repl != null) 
     m.appendReplacement(buf, Matcher.quoteReplacement(repl)); 
} 
String output = m.appendTail(buf).toString(); 

System.out.println(output); 

輸出

adklsfjb{TYPE 2 WITH x's}dklsjfnsdklj[type I with y's]adljfhjh 
+0

使用Java的正則表達式引擎+1極其巧妙地使用一種模式。感覺不得不贊成這一點。 –

+0

非常感謝您的回答!你肯定救了我! – mrawesome

+0

@mrawesome如果這是您正在尋找的答案,請點擊對號接受它,以便其他人可以看到您的問題已得到滿意答覆。 – Andreas

0

對於類型的變量${varname}您可以使用此模式:

(^|[^$])\$\{.*?\} 

而對於類型的變量$${varname}你可以使用你已經想好了:

\$\$\{.*?\\} 

示例代碼:

String input = "${beef} is a great thing to $${eat}. It has many ${health} benefits "; 
     input + "and is low in fat ${too}"; 

// single dollar sign variables 
System.out.println("single dollar sign variables:"); 
String pattern = "(?:^|[^$])(\\$\\{.*?\\})"; 
Pattern r = Pattern.compile(pattern); 

Matcher m = r.matcher(input); 
while (m.find()) { 
    System.out.println("Found value: " + m.group(1)); 
} 

// two dollar sign variables 
System.out.println("two dollar sign variables:"); 
pattern = "(\\$\\$\\{.*?\\})"; 
r = Pattern.compile(pattern); 

m = r.matcher(input); 
while (m.find()) { 
    System.out.println("Found value: " + m.group(1)); 
} 

輸出:

single dollar sign variables: 
Found value: ${beef} 
Found value: ${health} 
Found value: ${too} 
two dollar sign variables: 
Found value: $${eat} 

演示在這裏:

Rextester

+0

我還沒有在Java代碼中嘗試過您的答案,但是當我將其放在regexr.com上時,匹配的字符串還包含前綴字符。在你的輸入字符串中,前綴字符都是空格,所以它不應該是一個問題,但是我也處理URL,所以我可能需要再次過濾結果。無論如何感謝您的建議:) – mrawesome

+0

你錯誤地輸入了正則表達式。使用我的Java代碼中的正則表達式:'(?:^ | [^ $])(\ $ \ {。*?\\})......這應該可以正常工作。 –

相關問題