【问题标题】:Underscore to camel case except for certain prefixes骆驼大小写下划线,某些前缀除外
【发布时间】:2015-04-28 15:54:43
【问题描述】:

我目前正在创建一个 Java 程序来重写我们软件中一些过时的 Java 类。部分转换包括将变量名称从包含下划线更改为使用 camelCase。问题是,我不能简单地替换代码中的所有下划线。我们有一些带有常量的类,对于这些类,应该保留下划线。
如何用 stringLabel 替换像 string_label 这样的实例,但不要替换出现在前缀“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(); 
}

【问题讨论】:

  • 这里有问题吗?这听起来更像是一份状态报告,而不是求助请求。我没有看到问号,也没有说明您遇到了什么实际问题,也没有看到您尝试过什么。
  • 遵循的实际规则是什么?任何标识符符合Parameters?在 Parameters 类中,一个标识符可能会被一个简单的名称引用?
  • 我认为很明显我可以用“A”替换“_a”之类的内容,但我不确定如何跳过下划线直接出现在特定前缀之后的实例。跨度>
  • @Radiodef 以下是一些示例: 将field_name 转换为fieldNamefield_name.setText(Parameters.is_module_installed ? "Label1" : "Label2"); 转换为fieldName.setText(Parameters.is_module_installed ? "Label1" : "Label2");

标签: java regex camelcasing


【解决方案1】:

你可以试试这样的:

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 语法,但我希望你明白我的意思。对自己做一点解析会有很长的路要走。

【讨论】:

  • 我明白这一点。目标是真正替换使用 _ 而不是驼峰式大小写定义的字段名称,而不更改另一个类中存在的字段/常量。
  • 这正是我所需要的!谢谢你。在查看了我需要替换的所有实例之后,我几乎认为只要匹配以句点开头,无论前缀是什么,我都不想替换它,因为这可能意味着它是属于的字段/方法另一个班级。
  • 我希望您能进一步帮助我。我认为与其检查特定的前缀,不如假设一个字符串前面没有直接带有“.”的字符串应该被替换是安全的。所以类似:class.getPrimary_Id(primary_idField); 应该变成:class.getPrimary_Id(primaryIdField); 跳过包含值的下划线直接以“。”开头的位置。将防止从另一个不应替换下划线的类更改代码中引用的任何方法/字段。
  • 可能类似于"(?&lt;!\\.)[\\w_]*_(.)"。还有"[^.][\\w_]*_(.)"。我建议阅读后向链接。
【解决方案2】:

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

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

如果匹配,不要替换任何东西。

【讨论】:

  • 抱歉粗心,这可能更合适:\\bParameters.*?\\b(\\b 表示单词边界。)
猜你喜欢
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 2016-08-07
  • 1970-01-01
  • 2020-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多