Java 我如何逃脱'+';在模式匹配中突出显示关键字?
我正在用Java实现一个关键字高亮器。我使用Java 我如何逃脱'+';在模式匹配中突出显示关键字?,java,regex,escaping,Java,Regex,Escaping,我正在用Java实现一个关键字高亮器。我使用java.util.regex.Pattern突出显示字符串内容中的关键字(加粗)。下面的代码适用于字母数字关键字,但不适用于某些特殊字符。例如,在字符串内容中,我想突出显示具有特殊字符+(加号)的关键字c++,但它没有正确突出显示。如何转义++字符以突出显示c++ public static void main(String[] args) { String content = "java,c++,ejb,struts,j2ee,hibern
java.util.regex.Pattern
突出显示字符串内容中的关键字(加粗)。下面的代码适用于字母数字关键字,但不适用于某些特殊字符。例如,在字符串内容中,我想突出显示具有特殊字符+(加号)的关键字c++
,但它没有正确突出显示。如何转义++
字符以突出显示c++
public static void main(String[] args)
{
String content = "java,c++,ejb,struts,j2ee,hibernate";
System.out.println("CONTENT: " + content);
String highlight = "C++";
System.out.println("HIGHLIGHT KEYWORD: " + highlight);
//highlight = highlight.replaceAll(Pattern.quote("+"), "\\\\+");
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\b" + highlight + "\\b", java.util.regex.Pattern.CASE_INSENSITIVE);
System.out.println("PATTERN: " + pattern.pattern());
java.util.regex.Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
System.out.println("Match found!!!");
for (int i = 0; i <= matcher.groupCount(); i++) {
System.out.println(matcher.group(i));
content = matcher.replaceAll("<B>" + matcher.group(i) + "</B>");
}
}
System.out.println("RESULT: " + content);
}
但我仍然无法正确理解语法。有人能帮我解决这个问题吗?问题是
\b
单词边界锚不匹配,因为+
是一个非单词字符,我假设后面有一个空格也是一个非单词字符
单词边界\b
匹配从单词字符(\w
中的成员)到非单词字符(没有\w
的成员)的更改
此外,如果您想按字面意思匹配+
,则必须将其转义。这里您正在搜索C++
,这意味着至少匹配一个C
,++
是一个所有格量词,至少匹配一个C
,并且不会回溯
试着把你的模式改成这样
java.util.regex.Pattern.compile("\\b" + highlight + "(?=\s)", java.util.regex.Pattern.CASE_INSENSITIVE);
(?=\s)
是一个积极的前瞻,它将检查在突出显示的之后是否有空白
此外,您还需要查看您正在搜索的+。这应该可以满足您的需要:
Pattern pattern = Pattern.compile(
"\\b"
+ Pattern.quote(highlight)
+ "\\b",
Pattern.CASE_INSENSITIVE);
Update:你是对的,上面的C++不起作用(<代码> \b/COD>匹配单词边界,不承认++作为单词)。我们需要一个更复杂的解决方案:
Pattern pattern = Pattern.compile(
"\\b"
+ Pattern.quote(highlight)
+ "(?![^\\p{Punct}\\s])", // matches if the match is not followed by
// anything other than whitespace or punctuation
Pattern.CASE_INSENSITIVE);
更新以回应评论:似乎在模式创建中需要更多的逻辑。以下是为您创建模式的帮助器方法:
private static final String WORD_BOUNDARY = "\\b";
// edit this to suit your neds:
private static final String ALLOWED = "[^,.!\\-\\s]";
private static final String LOOKAHEAD = "(?!" + ALLOWED + ")";
private static final String LOOKBEHIND = "(?<!" + ALLOWED + ")";
public static Pattern createHighlightPattern(final String highlight) {
final Pattern pattern = Pattern.compile(
(Character.isLetterOrDigit(highlight.charAt(0))
? WORD_BOUNDARY : LOOKBEHIND)
+ Pattern.quote(highlight)
+ (Character.isLetterOrDigit(highlight.charAt(highlight.length() - 1))
? WORD_BOUNDARY : LOOKAHEAD),
Pattern.CASE_INSENSITIVE);
return pattern;
}
当我运行此方法时,我看不到任何输出(这很好:-)您需要的是:
Pattern.compile("\\Q"+highlight+"\\E", java.util.regex.Pattern.CASE_INSENSITIVE);
假设关键字不以标点符号开头或结尾,下面是一个注释正则表达式,它使用lookahead和lookahead来实现所需的匹配行为:
//编译正则表达式以匹配关键字或关键字短语。
java.util.regex.Pattern模式=java.util.regex.Pattern.compile(
“(?+1文档:@Tomalak实际上,更像Hm,链接本身是正确的,但很明显它在未编码的结尾部分断开了-或者你的意思是链接到Java1.6更好?@Tomalak是的,这就是我的意思(没有将直接链接添加到Pattern.quote(),lazy me)@Sean我不知道Java1.6Pattern.quote()在哪里)
方法会比1.5中的方法更好。甚至它们各自的文档都是完全相同的;-@Gnanam,我不确定用Java,\+
或\+
@Gnanam,将我的答案和@Sean答案结合起来。他的模式。引用(突出显示)
应该转义搜索字符串中的+
。@Gnanam,什么不起作用?代码现在看起来如何?它做错了什么?事实上,这完全失败了,甚至没有突出显示简单的关键字,如“java”、“ejb”等。它没有突出显示关键字“c”++“代码看起来也是这样:Pattern=Pattern.compile(“\\b”+Pattern.quote(highlight)+”(?=\\s)”,java.util.regex.Pattern.CASE\u不区分大小写);
@stema+1用于您的方法,但我认为OP的字符串中没有空格,所以您必须用一个负数替换正的前瞻(如我的回答中所示)我要突出显示的关键字应该是“独立”单词,而不是较大单词的一部分。例如,如果有一个字符串内容包含“java,javascript”,而我的关键字是“java”,则您的模式将在此处同时突出显示java和javascript。输出为:java,javascript
然后用\\b…将其包围起来,如下所示:java.util.regex.pattern.compile(“\\b\\Q”+highlight+”\\E\\b”,java.util.regex.pattern.不区分大小写)
即使尝试了\\b
,它也没有突出显示关键字c++
。是的!Sean的答案在这里似乎做得很好!但它也不完美。我认为您将不得不使用传统的拆分和检查单个字符串的方法!但还是让我们想想吧!
private static void testMatch(final String haystack, final String needle) {
final Matcher matcher = createHighlightPattern(needle).matcher(haystack);
if (!matcher.find())
System.out.println("Failed to find pattern " + needle);
while (matcher.find())
System.out.println("Found additional match: " + matcher.group() +
" for pattern " + needle);
}
public static void main(final String[] args) {
final String testString = "java,c++,hibernate,.net,asp.net,c#,spring";
testMatch(testString, "java");
testMatch(testString, "c++");
testMatch(testString, ".net");
testMatch(testString, "c#");
}
Pattern.compile("\\Q"+highlight+"\\E", java.util.regex.Pattern.CASE_INSENSITIVE);