Что такое граница слова в регулярных выражениях?
Я использую регулярные выражения Java в Java 1.6 (в частности, для анализа числового вывода) и не может найти точное определение \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
Ответы
Ответ 1
В большинстве диалектов регулярных выражений граница слова - это позиция между \w
и \w
(не слово char), либо в начале или конце строки, если она начинается или заканчивается (соответственно) с помощью символ слова ([0-9A-Za-z_]
).
Итак, в строке "-12"
она будет соответствовать до 1 или после 2. Черта не является символом слова.
Ответ 2
Граница слов может встречаться в одной из трех позиций:
- Перед первым символом в строке, если первый символ является символом слова.
- После последнего символа в строке, если последний символ является символом слова.
- Между двумя символами в строке, где один является символом слова, а другой не является символом слова.
Символы Word являются буквенно-цифровыми; знак минус - нет. Взято из учебника Regex.
Ответ 3
Граница слов - это позиция, которая либо предшествует символу слова, либо не сопровождается одним, либо сопровождается символом слова и не предшествует одному.
Ответ 4
Я говорю о том, что \b
-строчные границы регулярных выражений на самом деле here.
Короче говоря, theyre условный. Их поведение зависит от того, что рядом с ними.
# same as using a \b before:
(?(?=\w) (?<!\w) | (?<!\W) )
# same as using a \b after:
(?(?<=\w) (?!\w) | (?!\W) )
Иногда это не то, что вы хотите. См. Мой другой ответ для уточнения.
Ответ 5
Проверьте документацию по граничным условиям:
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")));
}
Когда вы распечатываете его, обратите внимание, что это результат:
[Я нашел значение - в моей строке.]
Это означает, что символ "-" не воспринимается как находящийся на границе слова, потому что он не считается символом слова. Похоже, что @brianary вроде бы избил меня до удара, так что он получает голосование.
Ответ 6
Я столкнулся с еще более серьезной проблемой при поиске текста для слов типа .NET
, C++
, C#
и C
. Вы могли бы подумать, что программисты лучше знают, чем назвать язык, что трудно написать для регулярных выражений.
В любом случае, это то, что я узнал (в основном из http://www.regular-expressions.info, что является отличным сайтом): во многих вариантах регулярного выражения, символы, которые сопоставляются коротким символьным классом \w
, являются символами, которые рассматриваются как словарные символы по границам слов. Java является исключением. Java поддерживает Unicode для \b
, но не для \w
. (Я уверен, что в то время была веская причина).
\w
обозначает символ слова. Он всегда соответствует символам ASCII [A-Za-z0-9_]
. Обратите внимание на включение подчеркивания и цифр (но не тире!). В большинстве вариантов, поддерживающих Unicode, \w
содержит много символов из других скриптов. Существует много несогласованности относительно того, какие символы фактически включены. Буквы и цифры из алфавитных сценариев и идеографов, как правило, включены. Пунктуация соединителя, отличная от символа подчеркивания, и числовые символы, которые не являются цифрами, могут быть включены или не включены. XML Schema и 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));
P.S. Я благодарю http://regexpal.com/, без которого мир регулярных выражений будет очень жалким!
Ответ 7
В процессе обучения регулярному выражению я действительно застрял в метасимволе, который есть \b
. Я действительно не понимал его смысла, когда я спрашивал себя: "что это такое, что это такое", повторяется. После некоторых попыток использования веб-сайта я слежу за розовыми вертикальными штрихами в каждом начале слов и в конце слов. В то время я хорошо это понял. Теперь это точно слово (\w
) -boundary.
Мое мнение - просто для понимания, ориентированного на понимание. Логику его следует изучить из других ответов.
![enter image description here]()
Ответ 8
Я хотел бы объяснить Алан Мур ответ
Граница слова - это позиция, которой предшествует либо символ слова, за которым не следует ни один, либо символ слова, за которым не следует ни один.
Предположим, у меня есть строка "Это a c at, а она потрясающая", и я должен заменить все вхождения на букву ' a 'только если эта буква существует в "границе слова", т.е. буква a
внутри' cat 'не должна заменяться.
Поэтому я буду выполнять регулярное выражение (в Python) как
re.sub("\ba","e", myString.strip())
//заменить a
на e
поэтому вывод будет
Это e
c at e
и она e
классная
Ответ 9
Граница слова \b используется, когда одно слово должно быть символом слова, а другое - не словом. Регулярное выражение для отрицательного числа должно быть
--?\b\d+\b
проверить работоспособность DEMO
Ответ 10
Я считаю, что ваша проблема связана с тем, что -
не является символом слова. Таким образом, граница слова будет соответствовать после -
, и поэтому не будет ее фиксировать. Границы слов совпадают перед первым и после последнего слова в строке, а также в любом месте, где перед символом слова или символом, отличным от слова, и после того, как это будет наоборот. Также обратите внимание, что граница слова является совпадением нулевой ширины.
Возможной альтернативой является
(?:(?:^|\s)-?)\d+\b
Это будет соответствовать любым числам, начинающимся с символа пробела и необязательной тире, и заканчивается на границе слова. Он также будет соответствовать числу, начинающемуся в начале строки.
Ответ 11
Я думаю, что это граница (т.е. символ) последнего совпадения или начало или конец строки.
Ответ 12
когда вы используете \\b(\\w+)+\\b
, что означает точное совпадение со словом, содержащим только слова-символы ([a-zA-Z0-9])
в вашем случае, например, установка \\b
в начале регулярного выражения примет -12
(с пробелом), но снова он не примет -12
(без пробела)
для ссылки на мои слова: https://docs.oracle.com/javase/tutorial/essential/regex/bounds.html