Java正则表达式与模式和匹配器

时间:2015-03-25 15:29:25

标签: java regex servlets

我正在使用Java中的Pattern和Matcher类, 我正在阅读模板文本,我想替换:

  1. src =“scripts / test.js”,src =“scripts / test.js?Id = $ {Id}”
  2. src =“Servlet?Template = scripts / test.js”,src =“Servlet?Id = $ {Id}& Template = scripts / test.js”
  3. 我正在使用以下代码执行案例2.:

    //strTemplateText  is the Template's text
    Pattern p2 = Pattern.compile("(?i)(src\\s*=\\s*[\"'])(.*?\\?)");
    Matcher m2 = p2.matcher(strTemplateText);
    strTemplateText = m2.replaceAll("$1$2Id=" +     CurrentESSession.getAttributeString("Id", "") + "&");
    

    上面的代码适用于案例2.但是如何创建一个正则表达式来组合案例1.和2.?

    谢谢

3 个答案:

答案 0 :(得分:1)

你不需要正则表达式。如果您将案例2更改为

  

Servlet?Template=scripts/test.js替换为Servlet?Template=scripts/test.js&Id=${Id}

您需要做的就是检查源字符串是否包含?,如果不添加?Id=${Id},则添加&Id=${Id}

毕竟

if (strTemplateText.contains("?") {
    strTemplateText += "&Id=${Id}";
}
else {
    strTemplateText += "?Id=${Id}";
}

完成这项工作。

甚至更短

strTemplate += strTemplateText.contains("?") ? "&Id=${Id}" : "?Id=${Id}";

答案 1 :(得分:0)

您的实际问题与您的示例代码不匹配。示例代码似乎处理更一般的情况,它替换实际的会话Id值而不是对一个的引用。下面的代码使示例代码更能说明您真正想要的内容,但同样的方法可以适应您在问题文本中提出的问题(使用更简单的正则表达式,甚至)。

话虽如此,我认为单一replaceAll()没有办法做到这一点,因为这两种情况的替换文字太不同了。如果你使用不同的方法,你可以在一次通过中使用一个正则表达式:

Pattern p2 = Pattern.compile("(src\\s*=\\s*)(['\"])([^?]*?)(\\?.*?)?\\2",
        Pattern.CASE_INSENSITIVE);
Matcher m2 = p2.matcher(strTemplateText);
StringBuffer revisedText = new StringBuffer();

while (m2.find()) {
    // Append the whole match except the closing quote
    m2.appendReplacement(revisedText, "$1$2$3$4");
    // group 4 is the optional query string; null if none was matched
    revisedText.append((m2.group(4) == null) ? '?' : '&');
    revisedText.append("Id=");
    revisedText.append(CurrentESSession.getAttributeString("Id", ""));
    // append a copy of the opening quote
    revisedText.append(m2.group(2));
}
m2.appendTail(revisedText);

strTemplateText = revisedText.toString();

这依赖于BetaRide的观察,即查询参数顺序并不重要,尽管相同的通用方法可以满足使Id成为第一个查询参数的要求,如问题所示。它还将模式中src属性的末尾与正确的结束分隔符匹配,您的模式无法解决(尽管需要避免匹配跨越多个src属性的文本)

请注意,上面没有任何内容可以防止添加重复的查询参数“Id”;这与问题中提出的正则表达式一致。如果你想通过上面的方法避免这种情况,那么在循环中你需要解析查询字符串(当有一个时)来确定是否已经存在'Id'参数。

答案 2 :(得分:0)

您可以执行以下操作:

//strTemplateText  is the Template's text
String strTemplateText = "src=\"scripts/test.js\"";
strTemplateText = "src=\"Servlet?Template=scripts/test.js\"";

java.util.regex.Pattern p2 = java.util.regex.Pattern.compile("(src\\s*=\\s*[\"'])(.*?)((?:[\\w\\s\\d.\\-\\#]+\\/?)+)(?:[?]?)(.*?\\=.*)*(['\"])");
java.util.regex.Matcher m2 = p2.matcher(strTemplateText);
System.out.println(m2.matches());
strTemplateText = m2.replaceAll("$1$2$3?Id=" + CurrentESSession.getAttributeString("Id", "") + (m2.group(4)==null? "":"&") + "$4$5");
System.out.println(strTemplateText);

它适用于两种情况。

  

如果您使用的是java> 1.6;然后,您可以使用自定义命名的组捕获功能来制作正则表达式exp。更易于阅读,更易于调试。