如何在java中使用java.util.regex匹配输入中的特定格式?

时间:2014-03-21 08:42:22

标签: java regex

INPUT

输入可以是以下任何一种形式,包含以下强制性内容 TXT {Any comma separated strings in any format}

String loginURL = "http://ip:port/path?username=abcd&location={LOCATION}&TXT{UE-IP,UE-Username,UE-Password}&password={PASS}";
String loginURL1 = "http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}&TXT{UE-IP,UE-Username,UE-Password}";
String loginURL2 = "http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}&username=abcd&location={LOCATION}&password={PASS}";
String loginURL3 = "http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}";
String loginURL4 = "http://ip:port/path?username=abcd&password={PASS}";

必需输出

1。 OutputURL对应于loginURL。

String outputURL = "http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}";
String outputURL1 = "http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}";
String outputURL2 = "http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}";
String outputURL3 = "http://ip:port/path?";
String outputURL4 = "http://ip:port/path?username=abcd&password={PASS}";

2。已删除的模式(如果有)

String deletedPatteren = TXT{UE-IP,UE-Username,UE-Password}

我的尝试

String loginURLPattern = TXT+"\\{([\\w-,]*)\\}&*";

System.out.println("1. ");
getListOfTemplates(loginURL, loginURLPattern);
System.out.println();

System.out.println("2. ");
getListOfTemplates(loginURL1, loginURLPattern);
System.out.println();

private static void getListOfTemplates(String inputSequence,String pattern){
    System.out.println("Input URL : " + inputSequence);
    Matcher templateMatcher =  Pattern.compile(pattern).matcher(inputSequence);
    if (templateMatcher.find() && templateMatcher.group(1).length() > 0) {
        System.out.println(templateMatcher.group(1));
        System.out.println("OutputURL : " + templateMatcher.replaceAll(""));
    }
}

获得OUTPUT

1. 
Input URL : http://ip:port/path?username=abcd&location={LOCATION}&TXT{UE-IP,UE-Username,UE-Password}&password={PASS}
UE-IP,UE-Username,UE-Password}&password={PASS
OutputURL : http://ip:port/path?username=abcd&location={LOCATION}&

2. 
Input URL : http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}&TXT{UE-IP,UE-Username,UE-Password}
UE-IP,UE-Username,UE-Password
OutputURL : http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}&

超越上图>

如果我添加任何字符串containing character like #,%,@ in between TXT{},那么我的代码会中断。

如何使用java.util.regex库实现它,以便用户可以在TXT{Any Comma Separated Strings}之间输入任何逗号分隔的字符串。

1 个答案:

答案 0 :(得分:4)

我建议使用Matcher.appendReplacement

public static void main(final String[] args) throws Exception {
    final String[] loginURLs = {
        "http://ip:port/path?username=abcd&location={LOCATION}&TXT{UE-IP,UE-Username,UE-Password}&password={PASS}",
        "http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}&TXT{UE-IP,UE-Username,UE-Password}",
        "http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}&username=abcd&location={LOCATION}&password={PASS}",
        "http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}",
        "http://ip:port/path?username=abcd&password={PASS}"};
    final Pattern patt = Pattern.compile("(\\?)?&?(TXT\\{[^}]++})(&)?");
    for (final String loginURL : loginURLs) {
        System.out.printf("%1$-10s %2$s%n", "Processing", loginURL);
        final StringBuffer sb = new StringBuffer();
        final Matcher matcher = patt.matcher(loginURL);
        while (matcher.find()) {
            final String found = matcher.group(2);
            System.out.printf("%1$-10s %2$s%n", "Found", found);
            if (matcher.group(1) != null && matcher.group(3) != null) {
                matcher.appendReplacement(sb, "$1");                
            } else {
                matcher.appendReplacement(sb, "$3");
            }
        }
        matcher.appendTail(sb);
        System.out.printf("%1$-10s %2$s%n%n", "Processed", sb.toString());
    }
}

输出:

Processing http://ip:port/path?username=abcd&location={LOCATION}&TXT{UE-IP,UE-Username,UE-Password}&password={PASS}
Found      TXT{UE-IP,UE-Username,UE-Password}
Processed  http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}

Processing http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}&TXT{UE-IP,UE-Username,UE-Password}
Found      TXT{UE-IP,UE-Username,UE-Password}
Processed  http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}

Processing http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}&username=abcd&location={LOCATION}&password={PASS}
Found      TXT{UE-IP,UE-Username,UE-Password}
Processed  http://ip:port/path?username=abcd&location={LOCATION}&password={PASS}

Processing http://ip:port/path?TXT{UE-IP,UE-Username,UE-Password}
Found      TXT{UE-IP,UE-Username,UE-Password}
Processed  http://ip:port/path

Processing http://ip:port/path?username=abcd&password={PASS}
Processed  http://ip:port/path?username=abcd&password={PASS}

正如您正确指出的那样,有3种可能的情况:

  1. " {TEXT}&安培;" - > ""
  2. "&安培; {TEXT}&安培;" - > "&安培;"
  3. " {TEXT}" - > ""
  4. 所以我们需要做的是测试正则表达式中的那些情况。这是模式:

    (\\?)?&?(TXT\\{[^}]++})(&)?
    

    说明:

    • (\\?)?可选地匹配并捕获?
    • &?可选择捕获&
    • (TXT\\{[^}]++})匹配并捕获TXT,然后是{,后跟一个或多个 }(占有),然后是{ {1}}(关闭括号不需要转义
    • }可选地匹配并捕获(&)?

    我们有3个小组:

    1. 可能是&
    2. 必填文字
    3. 可能是?
    4. 现在,当我们找到匹配项时,我们需要使用适当的案例&

      进行替换
      1..3

      如果群组if (matcher.group(1) != null && matcher.group(3) != null) { matcher.appendReplacement(sb, "$1"); } else { matcher.appendReplacement(sb, "$3"); } 1都存在

      我们必须遇到3;我们必须用"?"这是1组中的1

      否则我们会遇到$12

      在案例2中,我们需要替换为"&"并在3中使用"" 如果3群组2将持有"&"如果3它将保持""所以我们可以在这两种情况下用3替换。

      这里我只使用匹配组捕获$3部分。这意味着虽然替换了前导TXT{...}?,但它不在&中。我只想要String found之间的位,然后移动括号。

      请注意,我重复使用{} - 如果性能受到关注,您也可以reuse the Matcher。您应该始终重复使用Pattern,因为它(非常)昂贵。如果可以的话,将它存储在Pattern中 - 它的线程安全,匹配器不是。通常的方法是将static final存储在Pattern中,然后在方法的上下文中重用static final

      此外,使用Matcher比当前方法更有效,因为它只需要处理输入一次。你的方法解析了两次字符串。