如何在保持可选参数完整的同时创建正则表达式来替换已知字符串?

时间:2016-01-21 12:15:42

标签: java regex

我现在已经尝试了一段时间,但是没有做对: 在Java中,我试图创建一个正则表达式来匹配和替换字符串中的一个(对我来说已知)字符串,同时保持可选参数不变。

示例输入:

{067e6162-3b6f-4ae2-a171-2470b63dff00}
{067e6162-3b6f-4ae2-a171-2470b63dff00,number}
{067e6162-3b6f-4ae2-a171-2470b63dff00,number,integer}
{067e6162-3b6f-4ae2-a171-2470b63dff00,choice,1#one more item|1<another {067e6162-3b6f-4ae2-a171-2470b63dff00,number,integer} items}

(注意,最后一个示例包含对同一输入字符串的嵌套引用)。 格式始终用大括号{...}括起要替换的字符串,但带有逗号分隔参数的可选列表。

我想用数字替换输入字符串,例如对于上面的输入字符串,结果应为:

{2}
{2,number}
{2,number,integer}
{2,choice,1#one more item|1<another {2,number,integer} items}

理想情况下,我希望有一个足够灵活的正则表达式来处理(几乎)任何字符串作为要替换的模式,所以不仅仅是UUID类型的字符串,而且还有类似的东西:

A test string with {the_known_input_value_to_be_replaced,number,integer} not replacing the_known_input_value_to_be_replaced if its not in curly brackets of course.

最终应该是例如:

A test string with {3,number,integer} not replacing the_known_input_value_to_be_replaced if its not in curly brackets of course.

请注意,只有在输入字符串使用大括号时才能进行替换。 在Java中,我将能够在运行时构造模式,并将要替换的字符串详细考虑在内。

我试过,例如\{(067e6162-3b6f-4ae2-a171-2470b63dff00)(,?.*)\}(还没有java转义)和更通用的方法,例如\{(+?)(,?.*)\},但他们都没有做好。

来自regex ninjas的任何建议都非常感谢:)

1 个答案:

答案 0 :(得分:1)

如果已知的旧字符串始终出现在{之后,则可以使用

String result = old_text.replace("{" + my_old_keyword, "{" + my_new_keyword);

如果在花括号内部确实有多个已知字符串(并且没有要转义的转义大括号),则可以使用以下代码:

String input = "067e6162-3b6f-4ae2-a171-2470b63dff00 is outside {067e6162-3b6f-4ae2-a171-2470b63dff00,choice,067e6162-3b6f-4ae2-a171-2470b63dff00,1#one more item|1<another {067e6162-3b6f-4ae2-a171-2470b63dff00,number,067e6162-3b6f-4ae2-a171-2470b63dff00,integer} items} 067e6162-3b6f-4ae2-a171-2470b63dff00 is outside ";
String old_key = "067e6162-3b6f-4ae2-a171-2470b63dff00";
String new_key = "NEW_KEY";
List<String> chunks = replaceInBalancedSubstrings(input, '{', '}', old_key, new_key);
System.out.println(String.join("", chunks));

结果:067e6162-3b6f-4ae2-a171-2470b63dff00 is outside {{NEW_KEY,choice,NEW_KEY,1#one more item|1<another {NEW_KEY,number,NEW_KEY,integer} items} 067e6162-3b6f-4ae2-a171-2470b63dff00 is outside

replaceInBalancedSubstrings方法如下所示:

public static List<String> replaceInBalancedSubstrings(String s, Character markStart, Character markEnd, String old_key, String new_key) {
    List<String> subTreeList = new ArrayList<String>();
    int level = 0;
    int prevStart = 0;
    StringBuffer sb = new StringBuffer();
    int lastOpenBracket = -1;
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (level == 0) {
            sb.append(c);
        }
        if (c == markStart) {
            level++;
            if (level == 1) {
                lastOpenBracket = i;
                if (sb.length() > 0) {
                    subTreeList.add(sb.toString());
                    sb.delete(0, sb.length());
                }
            }
        }
        else if (c == markEnd) {
            if (level == 1) {
                subTreeList.add(s.substring(lastOpenBracket, i+1).replace(old_key, new_key)); // String replacement here
            }
            level--;
        }
    }
    if (sb.length() > 0) {
        subTreeList.add(sb.toString());
    }
    return subTreeList;
}

请参阅IDEONE demo

此代码仅处理平衡(嵌套)花括号内的子串内的替换。