使用正则表达式匹配字符串中的参数值

时间:2010-10-11 12:25:35

标签: java regex escaping

我有一个包含几个参数的字符串,例如

PARAM1="someValue", PARAM2="someOtherValue"...

对于日志输出,我想“隐藏”某些参数的值,即用***替换它们。

我使用以下正则表达式来匹配参数值,这对大多数情况都适用:

(PARMANAME=")[\w\s]*"

但是,此正则表达式仅匹配单词和空白字符。我想扩展它以匹配两个引号之间的所有字符。问题是,值本身可以包含(转义的)引号,例如:

PARAM="the name of this param is \"param\""

如何正确匹配(和替换)?

我的Java方法如下所示:

/**
 * @param input input string
 * @param params list of parameters to hide
 * @return string with the value of the parameter being replace by ***
 */
public static String hideParamValue(String input, final String... params)
{
    for (String param : params)
    {
        input = input.replaceAll("(" + param + "=)\\\"[\\w\\s]*\\\"", "$1***");
    }
    return input;
}

4 个答案:

答案 0 :(得分:4)

Escaped引号是Java中真正的PITA,但这应该可以解决问题:

public class Test
{
  public static String hideParamValue(String input, final String... params)
  {
    for (String param : params)
    {
      input = input.replaceAll(
        "(" + param + "=)\"(?:[^\"\\\\]|\\\\.)*\"",
        "$1***");
    }
    return input;
  }

  public static void main(String[] args)
  {
    String s = "PARAM1=\"a b c\", PARAM2=\"d \\\"e\\\" f\", PARAM3=\"g h i\"";
    System.out.println(s);
    System.out.println(hideParamValue(s, "PARAM2", "PARAM3"));
  }
}

输出:

PARAM1="a b c", PARAM2="d \"e\" f", PARAM3="g h i"
PARAM1="a b c", PARAM2=***, PARAM3=***

[^\"\\\\]匹配引号或反斜杠以外的任何一个字符。反斜杠必须用正则表达式的另一个反斜杠进行转义,然后必须为字符串文字转义每个反斜杠。但是引号在正则表达式中没有特殊含义,所以它只需要一个反斜杠。

(?:[^\"\\\\]|\\\\.)匹配除引号或反斜杠之外的任何内容,或反斜杠后跟任何内容。它会处理您的转义引号,并且还允许转义反斜杠和其他转义序列,而无需额外费用。

@axtavt建议的负面后瞻方法只处理转义引号,它将\\"视为反斜杠后跟一个转义引号,当它可能是一个转义反斜杠后跟一个引号。

答案 1 :(得分:1)

试试这个正则表达式:

PARAM="(?:[^"\\]|\\")*"

这只允许包含除"\\"之外的任何字符的序列。如果您想允许其他转义序列而不仅仅是\",您可以使用\\["rnt…]扩展它,例如也允许\r\n\t

答案 2 :(得分:1)

你必须将scaped双引号添加到mathing字符表达式中:

在您的字符串中转义的

[\w\s\\"]而不是[\w\s]将导致[\\w\\s\\\\\"]而不是[\\w\\s]

因此,最终代码将以

结果
/**
 * @param input input string
 * @param params list of parameters to hide
 * @return string with the value of the parameter being replace by ***
 */
public static String hideParamValue(String input, final String... params) {
    for (String param : params)
    {
        input = input.replaceAll("(" + param + "=)\\\"[\\w\\s\\\\\"]*\\\"", "$1***");
    }
    return input;
}

答案 3 :(得分:1)

在这种情况下,negative lookbehind可能很有用:

(PARAMNAME=").*?(?<!\\)"

s.replaceAll("(" + param + "=)\".*?(?<!\\\\)\"", "$1***");

(?<!\\)"表示"前面没有\,因此.*?(?<!\\)"表示尽可能短(由于reluctant *?)由"终止的任何字符,其中"前面没有\