我有一个包含几个参数的字符串,例如
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;
}
答案 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 *?
)由"
终止的任何字符,其中"
前面没有\
。