Что такое граница слова в регулярных выражениях?

Я использую регулярные выражения 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

Граница слов может встречаться в одной из трех позиций:

  1. Перед первым символом в строке, если первый символ является символом слова.
  2. После последнего символа в строке, если последний символ является символом слова.
  3. Между двумя символами в строке, где один является символом слова, а другой не является символом слова.

Символы 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