驼峰式下划线,某些前缀除外

Underscore to camel case except for certain prefixes

我目前正在创建一个 Java 程序来重写我们软件中一些过时的 Java 类。部分转换包括将变量名称从包含下划线更改为使用驼峰命名法。问题是,我不能简单地替换代码中的所有下划线。我们有一些 类 带有常量,对于那些,下划线应该保留。
如何将 string_label 之类的实例替换为 stringLabel,但不要替换出现在前缀 "Parameters." 之后的下划线?

我目前正在使用以下显然不能处理排除某些前缀的问题:

public String stripUnderscores(String line) { 
  Pattern p = Pattern.compile("_(.)");
  Matcher m = p.matcher(line);         
  StringBuffer sb = new StringBuffer(); 
  while(m.find()) { 
    m.appendReplacement(sb, m.group(1).toUpperCase()); 
  } 
  m.appendTail(sb); 
  return sb.toString(); 
}

也许你可以有另一个模式:

Pattern p = Pattern.compile("^Parameters.*"); //^ means the beginning of a line

如果匹配,请不要替换任何内容。

您可以尝试类似的方法:

Pattern.compile("(?<!(class\s+Parameters.+|Parameters\.[\w_]+))_(.)")

它使用 negative lookbehind.

使用某种理解作用域语义的重构工具可能会更好。

如果您只检查一个限定名称,例如 Parameters.is_module_installed,那么您将替换

class Parameters {
    static boolean is_module_installed;
}

失误。还有更多像这样的极端情况。 (import static Parameters.*;,等等,等等)

单独使用正则表达式对我来说似乎很麻烦。使例程更智能的一种方法是使用正则表达式来捕获标识符的表达式,然后您可以单独检查它:

static List<String> exclude = Arrays.asList("Parameters");

static String getReplacement(String in) {
    for(String ex : exclude) {
        if(in.startsWith(ex + "."))
            return in;
    }

    StringBuffer b = new StringBuffer();
    Matcher m = Pattern.compile("_(.)").matcher(in);
    while(m.find()) {
        m.appendReplacement(b, m.group(1).toUpperCase());
    }

    m.appendTail(b);
    return b.toString();
}

static String stripUnderscores(String line) { 
    Pattern p = Pattern.compile("([_$\w][_$\w\d]+\.?)+");
    Matcher m = p.matcher(line);         
    StringBuffer sb = new StringBuffer(); 
    while(m.find()) { 
        m.appendReplacement(sb, getReplacement(m.group())); 
    } 
    m.appendTail(sb); 
    return sb.toString(); 
}

但这仍然会失败,例如class Parameters { is_module_installed; }.

可以通过进一步分解每个表达式来使其更加健壮:

static String getReplacement(String in) {
    if(in.contains(".")) {
        StringBuilder result = new StringBuilder();

        String[] parts = in.split("\.");

        for(int i = 0; i < parts.length; ++i) {
            if(i > 0) {
                result.append(".");
            }

            String part = parts[i];

            if(i == 0 || !exclude.contains(parts[i - 1])) {
                part = getReplacement(part);
            }

            result.append(part);
        }

        return result.toString();
    }

    StringBuffer b = new StringBuffer();
    Matcher m = Pattern.compile("_(.)").matcher(in);
    while(m.find()) {
        m.appendReplacement(b, m.group(1).toUpperCase());
    }

    m.appendTail(b);
    return b.toString();
}

那会处理像

这样的情况
Parameters.a_b.Parameters.a_b.c_d

并输出

Parameters.a_b.Parameters.a_b.cD

这是不可能的 Java 语法,但我希望你明白我的意思。自己做一点解析会有很长的路要走。