这是我的正则表达式,我正在尝试搜索所有特殊字符,以便我可以逃脱它们。
(\(|\)|\[|\]|\{|\}|\?|\+|\\|\.|\$|\^|\*|\||\!|\&|\-|\@|\#|\%|\_|\"|\:|\<|\>|\/|\;|\'|\`|\~)
我的问题是,我不想只是在序列中出现时才会逃避某些特殊字符
喜欢这个(.*)
所以,让我们考虑一个例子。
Sting message = "Hi, Mr.Xyz! Your account number is :- (1234567890) , (,*) &$@%#*(....))(((";
根据当前的正则表达式逃脱后,我得到的是,
Hi, Mr\.Xyz\! Your account number is \:\- \(1234567890\) , \(,\*\) \&\$\@\%\#\*\(\.\.\.\.\)\)\(\(\(
但是不想逃避这部分(.*)
希望保持原样。
我的上述正则表达式仅用于搜索,所以我只是不想与此部分(.*)
匹配,我的问题将得到解决
任何人都可以建议没有逃避字符串那部分的正则表达式吗?
答案 0 :(得分:3)
请参阅@nhahtdh,了解如何使用正则表达式执行此操作。
作为替代方案,这是一个不使用正则表达式的解决方案,而是使用Guava的CharMatcher代替:
private static final CharMatcher SPECIAL
= CharMatcher.anyOf("allspecialcharshere");
private static final String NO_ESCAPE = "(.*)";
public String doEncode(String input)
{
StringBuilder sb = new StringBuilder(input.length());
String tmp = input;
while (!tmp.isEmpty()) {
if (tmp.startsWith(NO_ESCAPE)) {
sb.append(NO_ESCAPE);
tmp = tmp.substring(NO_ESCAPE.length());
continue;
}
char c = tmp.charAt(0);
if (SPECIAL.matches(c))
sb.append('\\');
sb.append(c);
tmp = tmp.substring(1);
}
return sb.toString();
}
答案 1 :(得分:2)
这个答案只是为了证明这种可能性。在生产代码中使用它是值得怀疑的。
可以使用Java String replaceAll
函数:
String input = "Hi, Mr.Xyz! Your account number is :- (1234567890) , (.*) &$@%#*(....))(((";
String output = input.replaceAll("\\G((?:[^()\\[\\]{}?+\\\\.$^*|!&@#%_\":<>/;'`~-]|\\Q(.*)\\E)*+)([()\\[\\]{}?+\\\\.$^*|!&@#%_\":<>/;'`~-])", "$1\\\\$2");
结果:
"Hi, Mr\.Xyz\! Your account number is \:\- \(1234567890\) , (.*) \&\$\@\%\#\*\(\.\.\.\.\)\)\(\(\("
另一项测试:
String input = "(.*) sdfHi test message <> >>>>><<<<f<f<,,,,<> <>(.*) sdf (.*) sdf (.*)";
结果:
"(.*) sdfHi test message \<\> \>\>\>\>\>\<\<\<\<f\<f\<,,,,\<\> \<\>(.*) sdf (.*) sdf (.*)"
<强>解释强>
原始正则表达式:
\G((?:[^()\[\]{}?+\\.$^*|!&@#%_":<>/;'`~-]|\Q(.*)\E)*+)([()\[\]{}?+\\.$^*|!&@#%_":<>/;'`~-])
请注意,当在字符串中指定正则表达式时,\
会再次转义,并且"
需要进行转义。字符串中生成的正则表达式可以在上面看到。
原始替换字符串:
$1\\$2
由于$
在替换字符串中具有特殊含义,并且您希望保持它为$2
,因此您需要转义\
以便\
1}}不会逃脱$
。将替换字符串放在带引号的字符串中,您需要将\
的数量加倍以逃避\
。
在我们解剖怪物之前,让我们谈谈这个想法。我们将使用非特殊字符,以及我们不想替换的序列,并尽可能多地使用。下一个字符将是一个不构成我们不想替换的序列的特殊字符,或者是字符串的结尾(这意味着我们找到了所有需要替换的字符,如果有的话)。
当然,我们可以认为任意字符串连续由以下许多模式组成:[0 or more (non-special character or special pattern not to be replace)][special character]
,字符串以[0 or more (non-special character or special pattern not to be replace)]
结尾。
replaceAll
的正则表达式一起使用时, \G
函数可能会找到不连续的匹配项,这些匹配项可以在序列的中间切换而不会被替换并将其弄乱。 \G
表示最后一场比赛的边界,可用于确保下一场比赛从最后一场比赛的开始处开始。
\G
:从上一场比赛开始
((?:[^()\[\]{}?+\\.$^*|!&@#%_":<>/;'`~-]|\Q(.\*)\E)*+)
:捕获0或更多,非特殊字符或不要替换的特殊模式。请注意,我已在+
之后添加了所有格限定符*
。当它找不到我们在此之后指定的特殊字符时,这将阻止引擎回溯。
[^()\[\]{}?+\\.$^*|!&@#%_":<>/;'`~-]
:特殊字符的否定字符类。
\Q(.*)\E
:特殊序列(.*)
不可替换,\Q
和\E
引用的字面值。
([()\[\]{}?+\\.$^*|!&@#%_":<>/;'`~-])
:捕获单个特殊字符。
整个正则表达式将匹配最小长度为1的字符串(特殊字符)。第一个捕获组包含不应替换的部分,第二个捕获组包含应替换的特殊字符。