Regex 正则表达式中的单词边界是什么,\b是否匹配连字符'-';?
我尝试使用正则表达式来匹配空格分隔的数字。 我找不到Regex 正则表达式中的单词边界是什么,\b是否匹配连字符'-';?,regex,word-boundary,Regex,Word Boundary,我尝试使用正则表达式来匹配空格分隔的数字。 我找不到\b(“单词边界”)的精确定义。 我假设-12将是一个“整数字”(由\b\-?\d+\b匹配),但这似乎不起作用。我很高兴能知道解决问题的方法 [我在Java 1.6中使用Java正则表达式] 例如: Pattern pattern = Pattern.compile("\\s*\\b\\-?\\d+\\s*"); String plus = " 12 "; System.out.println(&quo
\b
(“单词边界”)的精确定义。
我假设-12
将是一个“整数字”(由\b\-?\d+\b
匹配),但这似乎不起作用。我很高兴能知道解决问题的方法
[我在Java 1.6中使用Java正则表达式]
例如:
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
我认为这是最后一次匹配的边界(即字符跟随)或字符串的开头或结尾。我认为您的问题是因为
-
不是单词字符。因此,单词边界将在-
之后匹配,因此不会捕获它。单词边界在字符串中第一个单词字符之前和最后一个单词字符之后匹配,以及在它之前是单词字符或非单词字符,而在它之后是相反的任何位置匹配。还要注意,单词边界是零宽度匹配
一个可能的选择是
(?:(?:^|\s)-?)\d+\b
这将匹配以空格字符和可选破折号开头,以单词边界结尾的任何数字。它还将匹配从字符串开头开始的数字。在大多数正则表达式方言中,单词边界是介于
\w
和\w
(非单词字符)之间的位置,或者如果字符串以单词字符([0-9A-Za-z_uz])开头或结尾,则位于字符串的开头或结尾
因此,在字符串“-12”
中,它将在1之前或2之后匹配。破折号不是文字字符。查看有关边界条件的文档:
查看此示例:
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")));
}
打印时,请注意输出如下:
[我在字符串中找到了值-。]
这意味着“-”字符不在单词边界上,因为它不被视为单词字符。看起来@brianary有点击败了我,所以他得到了一张赞成票 单词边界可以出现在以下三个位置之一:
在字符串的第一个字符之前,如果第一个字符是单词字符李>
如果最后一个字符是单词字符,则在字符串中最后一个字符之后
在字符串中的两个字符之间,其中一个是单词字符,另一个不是单词字符李>
单词字符是字母数字;负号不是。
取自。单词边界是一个位置,前面有一个单词字符,后面没有一个,或者后面有一个单词字符,前面没有一个。我谈论的是\b
-风格的正则表达式边界实际上是什么
简而言之,它们是有条件的。他们的行为取决于他们的下一步
# same as using a \b before:
(?(?=\w) (?<!\w) | (?<!\W) )
# same as using a \b after:
(?(?<=\w) (?!\w) | (?!\W) )
#与之前使用a\b相同:
(?=\w)(?)?
有时这不是你想要的。请看我的其他详细答案。我在搜索文本时遇到了更糟糕的问题,比如.NET
、C++
、C#
和C
。你可能会认为计算机程序员比给一种难以正常编写的语言命名更清楚的ar表达式
总之,这就是我发现的(主要是从一个很棒的网站上总结出来的):在大多数风格的正则表达式中,与速记字符类\w
匹配的字符是按单词边界视为单词字符的字符。Java是一个例外。Java支持\b
的Unicode,但不支持\w
(我确信当时有充分的理由这样做)
\w
代表“单词字符”。它始终与ASCII字符相匹配[A-Za-z0-9.]
。请注意包含下划线和数字(但不是破折号!)。在大多数支持Unicode的版本中,\w
包含许多来自其他脚本的字符。关于实际包含的字符,存在很多不一致之处。通常包括来自字母脚本和表意文字的字母和数字。除下划线和数字符号以外的连接器标点符号不是数字ts可能包括,也可能不包括。XML模式和XPath甚至包括\w
中的所有符号。但Java、JavaScript和PCRE仅将ASCII字符与\w
匹配
这就是为什么基于Java的正则表达式搜索C++
,C#
或.NET
(即使你记得逃过句号和加号)会被\b
拧紧
注:我不确定如何处理文本中的错误,比如某人在句子末尾的句号后没有加空格。我允许这样做,但我不确定这样做是否一定正确
无论如何,在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));
另外,我要感谢没有他,正则表达式的世界将非常悲惨!当您使用\\b(\\w++)\\b
时,这意味着与仅包含单词字符的单词完全匹配([a-zA-Z0-9])
例如,在您的情况下,在正则表达式的开头设置\\b
将接受-12
(带空格),但它同样不会接受-12
(无空格)
为了证明我的话:在学习正则表达式的过程中,我真的被困在了元字符\b
中。当我问自己“它是什么,它是什么”时,我确实不理解它的意思重复。在使用一些尝试之后,我注意到单词开头和结尾的粉红色垂直虚线。我当时很好地理解了它的意思。它现在正是单词(\w
)-boundary
我的观点是非常正确的
--?\b\d+\b