题
我在 Java 1.6 中使用 Java 正则表达式(尤其是解析数字输出),并且找不到精确的定义 \b
(“字边界”)。我原以为 -12
将是一个“整数词”(匹配 \b\-?\d+\b
)但这似乎不起作用。我很高兴知道匹配空格分隔数字的方法。
例子:
Pattern pattern = Pattern.compile("\\s*\\b\\-?\\d+\\s*");
String plus = " 12 ";
System.out.println(""+pattern.matcher(plus).matches());
String minus = " -12 ";
System.out.println(""+pattern.matcher(minus).matches());
pattern = Pattern.compile("\\s*\\-?\\d+\\s*");
System.out.println(""+pattern.matcher(minus).matches());
这将返回:
true
false
true
解决方案
一个字边界,在大多数的正则表达式的方言,是字符串的\w
和\W
(非字字符),或在开始或结束之间的位置上,如果它开始或用字字符的端部(分别)([0-9A-Za-z_]
)
所以,在串"-12"
,它将在1之前匹配或2后的破折号不是一个单词的字符。
其他提示
字边界可以出现在以下三个位置之一:
- 如果第一个字符是单词字符,则在字符串中的第一个字符之前。
- 在字符串中的最后一个字符之后,如果最后一个字符是单词字符。
- 字符串中的两个字符之间,其中一个是单词字符,另一个不是单词字符。
单词字符是字母数字;减号则不是。取自 正则表达式教程.
一个字边界是或者通过一个单词字符之前和后面没有一个,或随后的单词的字符,而不是由一个前面的位置上。
我谈什么\b
风格的正则表达式的边界实际上是的此处。
在短故事是,他们的条件即可。他们的行为取决于他们旁边的是什么。
# same as using a \b before:
(?(?=\w) (?<!\w) | (?<!\W) )
# same as using a \b after:
(?(?<=\w) (?!\w) | (?!\W) )
有时,这不是你想要的。看我为制定其他的答案。
检查出文档上的边界条件:
http://java.sun.com/docs /books/tutorial/essential/regex/bounds.html
检查出这个示例:
public static void main(final String[] args)
{
String x = "I found the value -12 in my string.";
System.err.println(Arrays.toString(x.split("\\b-?\\d+\\b")));
}
在将其打印出来,注意到输出是这样的:
[I中发现的值 - 在我的字符串。]
这意味着,“ - ”字符不被拾取作为一个字的边界上,因为它不被认为是一个字符。貌似还挺@brianary打我一记重拳,那么他得到的赞成票。
我像.NET
,C++
,C#
和C
词搜索文本时遇到了一个更糟糕的问题。你可能会认为计算机程序员会知道比来命名一种语言的东西是很难写的正则表达式。
在\w
代表“字字符”。它总是相匹配的ASCII字符[A-Za-z0-9_]
。注意下划线和数字列入(但不冲!)。在支持Unicode最口味,\w
包括来自其他脚本多个字符。有哪些字符实际上包含了很多不一致的。从字母文字和象形文字字母和数字通常被包括在内。连接器标点符号比下划线和不是数字可以或可以不被包括数字符号等。 XML架构和XPath甚至还包括在\w
所有符号。但Java,JavaScript和PCRE比赛仅ASCII字符\w
。
这是C++
,C#
或.NET
(即使你还记得逃脱周期和加号)由\b
被拧紧。为什么基于Java的正则表达式搜索
请注意:我不知道该怎么做文字错误,就像当有人一段时间在一个句子结束后不留一个空白。我允许它,但我不知道它是一定要做正确的事。
总之,在Java中,如果你正在寻找的那些奇怪的命名语言的文本,你需要前后空格和标点符号指示器来更换\b
。例如:
public static String grep(String regexp, String multiLineStringToSearch) {
String result = "";
String[] lines = multiLineStringToSearch.split("\\n");
Pattern pattern = Pattern.compile(regexp);
for (String line : lines) {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
result = result + "\n" + line;
}
}
return result.trim();
}
然后,在测试或主要功能:
String beforeWord = "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|^)";
String afterWord = "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|$)";
text = "Programming in C, (C++) C#, Java, and .NET.";
System.out.println("text="+text);
// Here is where Java word boundaries do not work correctly on "cutesy" computer language names.
System.out.println("Bad word boundary can't find because of Java: grep with word boundary for .NET="+ grep("\\b\\.NET\\b", text));
System.out.println("Should find: grep exactly for .NET="+ grep(beforeWord+"\\.NET"+afterWord, text));
System.out.println("Bad word boundary can't find because of Java: grep with word boundary for C#="+ grep("\\bC#\\b", text));
System.out.println("Should find: grep exactly for C#="+ grep("C#"+afterWord, text));
System.out.println("Bad word boundary can't find because of Java:grep with word boundary for C++="+ grep("\\bC\\+\\+\\b", text));
System.out.println("Should find: grep exactly for C++="+ grep(beforeWord+"C\\+\\+"+afterWord, text));
System.out.println("Should find: grep with word boundary for Java="+ grep("\\bJava\\b", text));
System.out.println("Should find: grep for case-insensitive java="+ grep("?i)\\bjava\\b", text));
System.out.println("Should find: grep with word boundary for C="+ grep("\\bC\\b", text)); // Works Ok for this example, but see below
// Because of the stupid too-short cutsey name, searches find stuff it shouldn't.
text = "Worked on C&O (Chesapeake and Ohio) Canal when I was younger; more recently developed in Lisp.";
System.out.println("text="+text);
System.out.println("Bad word boundary because of C name: grep with word boundary for C="+ grep("\\bC\\b", text));
System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
// Make sure the first and last cases work OK.
text = "C is a language that should have been named differently.";
System.out.println("text="+text);
System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
text = "One language that should have been named differently is C";
System.out.println("text="+text);
System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
//Make sure we don't get false positives
text = "The letter 'c' can be hard as in Cat, or soft as in Cindy. Computer languages should not require disambiguation (e.g. Ruby, Python vs. Fortran, Hadoop)";
System.out.println("text="+text);
System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
P.S。我对 http://regexpal.com/ 的感谢,没有他们的正则表达式的世界将是非常惨!
在学习正则表达式的过程中,我是真的卡住在其\b
元字符。我确实不理解它的意思,而我是在问自己“的它是什么,它是的什么”重复。一些尝试使用的网站后,我注意在每次的开始粉色垂直破折号字和以字的末尾。我得到了它的当时的意思很好。它现在准确的字(\w
)-boundary 强>
我的视图仅仅是非常理解为本。的背后逻辑应该从另一答案进行检查。
我相信你的问题是由于这样的事实,-
不是一个单词字符。因此,这个词边界将-
后匹配,因此将不会捕捉到它。单词边界之前的第一和字符串,以及在那里之前,它是一个单词字符和非单词字符的任何地方的最后一个字后的字符匹配,和之后是相反的。还要注意,字边界是零宽度匹配。
一种可能的替代方法是
(?:(?:^|\s)-?)\d+\b
这将匹配开头的空格字符和一个可选的短划线和在字边界结束的任何数字。它也将匹配起始于字符串的开头的数。
我认为它是在最后一次匹配或字符串的开头或结尾的(以下即字符)的边界。
当您使用\\b(\\w+)+\\b
这意味着完全匹配与字仅包含单词字符([a-zA-Z0-9])
在您的情况下,例如在正则表达式的开头设定\\b
将接受-12
(用空间),但再次它不会接受-12
(无空间)
供参考,以支持我的话:的https://文档。 oracle.com/javase/tutorial/essential/regex/bounds.html