带问号和单词边界的Java正则表达式精确匹配

带问号和单词边界的Java正则表达式精确匹配,java,regex,Java,Regex,在java中,我试图确定一个用户输入的字符串(意思是我不知道输入将是什么)是否正好包含在另一个字符串中,在单词边界上。因此,输入的不应在文本中匹配,不存在匹配。当输入的字符串中有标点符号时,我遇到了一些问题,需要一些帮助 没有标点符号,效果很好: String input = "string contain"; Pattern p = Pattern.compile("\\b" + Pattern.quote(input) + "\\b"); //both should and do matc

在java中,我试图确定一个用户输入的字符串(意思是我不知道输入将是什么)是否正好包含在另一个字符串中,在单词边界上。因此,
输入的
不应在文本中匹配,
不存在匹配
。当输入的字符串中有标点符号时,我遇到了一些问题,需要一些帮助

没有标点符号,效果很好:

String input = "string contain";
Pattern p = Pattern.compile("\\b" + Pattern.quote(input) + "\\b");

//both should and do match
System.out.println(p.matcher("does this string contain the input").find());
System.out.println(p.matcher("does this string contain? the input").find());
但是,当输入中有问号时,与单词边界的匹配似乎不起作用:

String input = "string contain?";
Pattern p = Pattern.compile("\\b" + Pattern.quote(input) + "\\b");

//should not match - doesn't
System.out.println(p.matcher("does this string contain the input").find());

//expected match - doesn't
System.out.println(p.matcher("does this string contain? the input").find());

//should not match - doesn't
System.out.println(p.matcher("does this string contain?fail the input").find());
任何帮助都将不胜感激。

您可以使用:

Pattern p = Pattern.compile("(\\s|^)" + Pattern.quote(input) + "(\\s|$)");
//---------------------------^^^^^^^----------------------------^^^^^^^
对于字符串,您将获得:

does this string contain the input       -> false
does this string contain? the input      -> true
does this fail the input string contain? -> true
does this string contain?fail the input  -> false
string contain? the input                -> true


其思想是,匹配包含
输入+空格的字符串,或
以您的输入结束

使用单词边界进行匹配:
\b

Java正则表达式实现将以下字符视为单词字符:
\w
:=
[a-zA-Z_0-9]

任何非单词字符都只是上述组之外的字符
[^\w]
:=
[^a-zA-Z_0-9]

单词边界是从
[a-zA-Z_0-9]
[^a-zA-Z_0-9]
的过渡,反之亦然


对于输入
“此字符串是否包含?输入”
和文字模式
\\b\\q字符串包含?\\E\\b
最后一个单词边界
\\b
在输入文本中从
的转换,因此,根据上面的定义,这意味着它不是一个单词边界

之间没有单词边界,因为没有相邻的单词字符;这就是你的模式不匹配的原因。您可以将其更改为:

Pattern.compile("(^|\\W)" + Pattern.quote(input) + "($|\\W)");
匹配输入字符或非单词字符的开头-模式-输入字符或非单词字符的结尾。或者,更好的做法是,使用负向后看和负向前看:

Pattern p = Pattern.compile("(?<!\\w)" + Pattern.quote(input) + "(?!\\w)");

Pattern p=Pattern.compile(“(?@quackenator通过添加
Pattern.quote()
您不必转义任何特殊字符
应该失败!?
失败!
匹配(省去一个问号以避免混淆)好问题@steffen-是-希望将输入中不直接存在的任何标点符号视为“单词边界”的一部分“另外,请参见。在右侧部分起作用,因为它只匹配
包含?
之后的空格,但不匹配另一个
。在
中的左侧如何?
@steffen您可以试着使用
这个字符串是否包含?输入是否匹配正确,如果
字符串输入=”字符串包含?“
好的,现在您已经将左手侧抬起,与部分转动的右手侧一样好;-)使用
检查此字符串是否包含输入
字符串是否包含?
。我猜应该匹配,但它不匹配。不,我的朋友,根据OP
的第三个示例,这不应该匹配//不应该匹配-不应该系统.out.println(p.matcher(“此字符串是否包含?输入失败”).find())
您只需将fail by
f
替换为?
我错了@steffen:)不,恐怕您错了。第三个示例不应该匹配,因为下面有一个单词字符。如果有非单词字符出现,它应该匹配。这就是问题所在。因为如果
在两者之间,这是您的单词边界。对于您的输入序列,“此字符串是否包含?!输入失败”,
string包含不匹配,但
字符串包含?
不匹配。这是一致的。对不起-我意识到我的错误,在看到你的回复之前删除了我的评论。还有一点,如果文本以输入结尾,它似乎不匹配,那么在本例中,
字符串是否包含?
将失败,但是
字符串是否包含(带空格)很好。总有一天我会学得更好@佐恩先生,两人都很般配。阅读最后一行:如果后面没有单词字符,则匹配。你的两个例子都不是这样,所以它对两个字符串都有效。啊-我想我抓住了第二个模式-这是有效的