有 Java 编程相关的问题?

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

正则表达式Java 8查找和替换匹配字符串

我试图在errorMessage中从messages.properties中找到一个字符串,如果errorMessage有该字符串,我需要用相应的值替换它

我有如下messages.properties

inv_date=INVOICE DATE
inv_id=INVOICE NUMBER
cl_id=CLIENT ID
lf_matter_id=LAW FIRM MATTER ID
inv_total_net_due=INVOICE TOTAL
(inv_start_date|invoice start date)=BILLING START DATE
(inv_end_date|invoice end date)=BILLING END DATE
inv_desc=INVOICE DESCRIPTION
units=LINE ITEM NUMBER OF UNITS
discount_amount=LINE ITEM ADJUSTMENT AMOUNT
total_amount=LINE ITEM TOTAL
(charge_date|charge date)= LINE ITEM DATE
acca_task=LINE ITEM TASK CODE
acca_expense=LINE ITEM EXPENSE CODE
acca_activity= LINE ITEM ACTIVITY CODE
(tk_id|time keeper id)=TIMEKEEPER ID
charge_desc=LINE ITEM DESCRIPTION
lf_id=LAW FIRM ID
(BaseRate|Rate|tk_rate)=LINE ITEM UNIT COST
tk_level=TIMEKEEPER CLASSIFICATION
cl_matter_id=CLIENT MATTER ID

我的errorMesage可以有任何(左侧)字符串,我需要用右侧字符串值替换它

下面是几个示例错误消息

String errorMesage1 = "Line 3 : Could not parse inv_date value" 
String errorMesage2 = "Line : 1 BaseRate is a required field"

下面是我转换错误消息的方法

public static String toUserFriendlyErrorMessage(String message) {
    ResourceBundle rb = ResourceBundle.getBundle("messages");
    for(String key : rb.keySet()){
        String header = rb.getString(key);
        if(message.contains(key)) {
          return message.replaceAll(key, rb.getString(key));           
        }
    }
    return message;

}

以下是预期产出: 对于errorMessage1,它工作正常

System.out.println(toUserFriendlyErrorMessage(errorMessage1)); ==> Line 3 : Could not parse INVOICE DATE value 

但是对于errorMessage2,它不起作用。它不会用LINE ITEM UNIT COST替换BaseRate

System.out.println(toUserFriendlyErrorMessage(errorMessage2)); ==> Line : 1 BaseRate is a required field

有没有办法找到多个字符串的出现,并用相应的值替换它

例如:查找(BaseRate|Rate|tk_rate)并将字符串替换为LINE ITEM UNIT COST

我还想知道这个方法是否可以在Java8中进一步简化


共 (1) 个答案

  1. # 1 楼答案

    我认为您应该重新考虑您的设计,为几个“别名”使用单独的键,或者可能更好:完全没有别名,每个替换只使用一个键。问题在于,这些属性文件中的键不应该包含空格或空格,因此无法正确解析文件。如果打印键,您将看到它们在第一个空格处被截断,例如(inv_start_date|invoice start date)变为(inv_start_date|invoice

    当然,这也意味着,即使您将这些“别名”拆分为单独的键,也不能有像invoice start date这样的键,因为它仍然包含空格,并且无法正确解析

    可以将这些替换内容放入Java源代码中的正则表达式中:

    static Map<String, String> replacements = new HashMap<>();
    static {
        replacements.put("inv_date", "INVOICE DATE");
        replacements.put("(BaseRate|Rate|tk_rate)", "LINE ITEM UNIT COST");
        // ... more stuff ...
    }
    

    或者手动解析文件,在=处拆分字符串并将其放入Map

    因为像(BaseRate|Rate|tk_rate)这样的键实际上是有效的正则表达式,所以您可以使用^{}在它们的所有变体中替换它们。如果它们不包含在字符串中,replaceAll将什么也不做,因此contains检查实际上是不必要的

    public static String toUserFriendlyErrorMessage(String message) {
        for (String key : replacements.keySet()) {
            message = message.replaceAll(key, replacements.get(key));
        }
        return message;
    }
    

    示例输出:

    Line 3 : Could not parse INVOICE DATE value
    Line : 1 LINE ITEM UNIT COST is a required field
    

    或者,如果您想使用一些“Java8魔术”,您可以使用reduce,但就个人而言,我认为循环更具可读性

        return replacements.keySet().stream()
                .reduce(message, (s, k) -> s.replaceAll(k, replacements.get(k)))
                .toString();