有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有模式和匹配器的Java正则表达式

我使用的是Java中的模式和匹配器类, 我正在阅读模板文本,我想替换:

  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”

我使用下面的代码来执行案例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。但是我如何创建一个正则表达式来结合这两种情况呢。2

谢谢!


共 (3) 个答案

  1. # 1 楼答案

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

    replace Servlet?Template=scripts/test.js with Servlet?Template=scripts/test.js&Id=${Id}

    你需要做的就是检查源字符串是否包含一个?如果不是add ?Id=${Id}否则add &Id=${Id}

    毕竟

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

    这是我的工作

    甚至更短

    strTemplate += strTemplateText.contains("?") ? "&Id=${Id}" : "?Id=${Id}";
    
  2. # 2 楼答案

    您可以执行以下操作:

    //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);
    

    这两种情况都适用

    If you are using java > 1.6; then, you could use custom-named group-capturing features for making the regex exp. more human-readable and easier to debug.

  3. # 3 楼答案

    您的实际问题与示例代码不太匹配。示例代码似乎处理了更一般的情况,它用实际的会话Id值代替对会话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”参数