簡體   English   中英

Java PatternSyntaxException:字符串替換非法重復嗎?

[英]Java PatternSyntaxException: Illegal repetition on string substitution?

我正在嘗試編寫一個將接受String的方法,檢查它是否包含某些令牌(例如${fizz}${buzz}${foo}等),並將每個令牌替換為一個新的字符串從Map<String,String>

例如,如果我將此方法傳遞給以下字符串:

“現在的$ {fizz}牛怎么樣了。$ {buzz}的形狀奇怪的$ {foo}。”

並且如果該方法查詢了以下Map<String,String>

Key             Value
==========================
"fizz"          "brown"
"buzz"          "arsonist"
"foo"           "feet"

那么結果字符串將是:

“現在是棕色的母牛。縱火犯的腳怪異。”

這是我的方法:

String substituteAllTokens(Map<String,String> tokensMap, String toInspect) {
    String regex = "\\$\\{([^}]*)\\}";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(toInspect);
    while(matcher.find()) {
        String token = matcher.group();     // Ex: ${fizz}
        String tokenKey = matcher.group(1); // Ex: fizz
        String replacementValue = null;

        if(tokensMap.containsKey(tokenKey))
            replacementValue = tokensMap.get(tokenKey);
        else
            throw new RuntimeException("String contained an unsupported token.");

        toInspect = toInspect.replaceFirst(token, replacementValue);
    }

    return toInspect;
}

運行此命令時,出現以下異常:

Exception in thread "main" java.util.regex.PatternSyntaxException: Illegal repetition near index 0
${fizz}
^
    at java.util.regex.Pattern.error(Pattern.java:1730)
    at java.util.regex.Pattern.closure(Pattern.java:2792)
    at java.util.regex.Pattern.sequence(Pattern.java:1906)
    at java.util.regex.Pattern.expr(Pattern.java:1769)
    at java.util.regex.Pattern.compile(Pattern.java:1477)
    at java.util.regex.Pattern.<init>(Pattern.java:1150)
    at java.util.regex.Pattern.compile(Pattern.java:840)
    at java.lang.String.replaceFirst(String.java:2158)
    ...rest of stack trace omitted for brevity (but available upon request!)

我為什么得到這個? 正確的解決方法是什么? 提前致謝!

${fizz}

{是正則表達式引擎的指示符,您即將開始一個重復指示符,例如{2,4} ,表示“是先前標記的2到4倍”。 但是{f是非法的,因為必須在其后加上數字,所以它會引發異常。

您需要轉義所有正則表達式元字符(在本例中${} )(嘗試使用http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html#quote( java.lang.String) ),或使用其他方法將字符串替換為字符串,而不是將正則表達式替換為字符串。

正如Patashu指出的那樣,問題出在replaceFirst(token, replacementValue) ,它在第一個參數中需要一個正則表達式,而不是文字。 將其更改為replaceFirst(Pattern.quote(token), replacementValue) ,您會做的很好。

我還對第一個正則表達式進行了一些更改,因為使用+而不是*可以使其運行得更快,但這不是必需的。

static String substituteAllTokens(Map<String,String> tokensMap, String toInspect) {
    String regex = "\\$\\{([^}]+)\\}";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(toInspect);
    String result = toInspect;
    while(matcher.find()) {
        String token = matcher.group();     // Ex: ${fizz}
        String tokenKey = matcher.group(1); // Ex: fizz
        String replacementValue = null;

        if(tokensMap.containsKey(tokenKey))
            replacementValue = tokensMap.get(tokenKey);
        else
            throw new RuntimeException("String contained an unsupported token.");

        result = result.replaceFirst(Pattern.quote(token), replacementValue);
    }

    return result;
}

改編自Matcher.replaceAll

boolean result = matcher.find();
if (result) {
    StringBuffer sb = new StringBuffer();
    do {
        String tokenKey = matcher.group(1); // Ex: fizz
        String replacement = Matcher.quoteReplacement(tokensMap.get(tokenKey));
        matcher.appendReplacement(sb, replacement);
        result = matcher.find();
    } while (result);
    matcher.appendTail(sb);
    return sb.toString();
}

您可以使RegEx有點難看,但這會起作用

String regex = "\\$[\\{]([^}]*)[\\}]";

使用String-replaceAll。 用於測試“ SESSIONKEY1”的樣本輸入字符串:

“ $ {SOMESTRING.properties.SESSIONKEY1}”

    String pattern = "\\\"\\$\\{SOMESTRING\\.[^\\}]+\\}\\\""; 
    System.out.println(pattern);
    String result = inputString.replaceAll(pattern, "null");
    return result.toString();

暫無
暫無

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

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