Java 8 查找并替换匹配的字符串

标签 java regex string 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 它不起作用。它不会将 BaseRate 替换为 LINE ITEM UNIT COST

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

有没有办法找到多个字符串的出现并将其替换为相应的值?

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

我还想知道这个方法能否在 Java 8 中进一步简化?

最佳答案

我认为你应该重新考虑你的设计并为几个“别名”使用单独的键 - 或者可能更好:根本没有别名,每次替换只用一个键。问题是这些属性文件中的键不应该包含空格——括号或不包含空格——所以文件没有被正确解析。如果打印键,您会看到它们在第一个空格处被截断,例如(inv_start_date|invoice start date) 变为 (inv_start_date|invoice

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

可以将这些替换放入 Java 源代码中的常规 Map 中:

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替换它们的所有变体。如果它们不包含在字符串中,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

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

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

关于Java 8 查找并替换匹配的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29570648/

相关文章:

java - 默认区域设置和数字格式

c# - C# Unity 中的正则表达式

regex - 崩溃计划和正则表达式 - 根据文件名排除文件

javascript - 用于获取 html 起始标签的正则表达式

java - 删除 Java 上重复的扩展文件

java - 如何检查字符串是否为数字

javascript - 将字符串拆分为 n 长度的数组

java - 通过计划任务进行批量操作的正确方法?

java - 如何从mysql中的两个表中获取值,其中一个表不同,另一个表多个值?

java - 使用路径打开并运行文件