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

StackOverflow https://stackoverflow.com/questions/1324676

  •  19-09-2019
  •  | 
  •  

Вопрос

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

Решение

Граница слова в большинстве диалектов регулярных выражений — это позиция между \w и \W (символ, не являющийся словом), или в начале или конце строки, если она начинается или заканчивается (соответственно) символом слова ([0-9A-Za-z_]).

Итак, в строке "-12", оно будет соответствовать до 1 или после 2.Тире не является словесным символом.

Другие советы

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

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

Символы слова являются буквенно-цифровыми;знака минус нет.Взято из Учебник по регулярным выражениям.

Граница слова — это позиция, которой либо предшествует словесный символ и не следует за ним, либо за которой следует словесный символ и которому не предшествует ни один.

Я говорю о том, что \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")));
    }

Когда вы распечатаете его, обратите внимание, что результат выглядит следующим образом:

[Я нашел значение - в своей строке.]

Это означает, что символ «-» не считается находящимся на границе слова, поскольку он не считается символом слова.Похоже, @brianary немного опередил меня, поэтому он получил положительный голос.

Я столкнулся с еще более серьезной проблемой при поиске в тексте таких слов, как .NET, C++, C#, и C.Вы могли бы подумать, что программисты знают, что лучше не называть язык чем-то, для чего сложно написать регулярные выражения.

Во всяком случае, вот что я узнал (в основном из http://www.regular-expressions.info, отличный сайт):В большинстве разновидностей регулярных выражений символы, соответствующие классу сокращенных символов. \w — это символы, которые рассматриваются как символы слова по границам слов.Ява является исключением.Java поддерживает Unicode для \b но не для \w.(Я уверен, что в то время для этого была веская причина).

А \w означает «символ слова».Он всегда соответствует символам ASCII. [A-Za-z0-9_].Обратите внимание на подчеркивание и цифры (но не тире!).В большинстве версий, поддерживающих Unicode, \w включает в себя множество персонажей из других сценариев.Существует много несоответствий относительно того, какие персонажи на самом деле включены.Обычно включаются буквы и цифры алфавитного алфавита и иероглифов.Знаки пунктуации соединителя, кроме подчеркивания и числовых символов, не являющихся цифрами, могут включаться или не включаться.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));

P.S.Моя благодарность http://regexpal.com/ без которого мир регулярных выражений был бы очень несчастен!

В ходе изучения регулярных выражений я действительно застрял в метасимволе, который \b.Я действительно не понял его смысла, пока спрашивал себя: "что это такое, что это такое"неоднократно.После некоторых попыток с помощью веб-сайт, я обращаю внимание на розовые вертикальные черточки в начале и в конце слов.В то время я хорошо понял это значение.Это сейчас точно слово(\w)-граница.

Моя точка зрения просто очень ориентирована на понимание.Логику этого следует изучить на основе других ответов.

enter image description here

Я хотел бы объяснить Алан Мурответ

Граница слова — это позиция, которой либо предшествует словесный символ и не следует за ним, либо за которой следует словесный символ и которому не предшествует ни один.

Предположим, у меня есть строка «Это а сат и она акруто», и я должен заменить все вхождения буквы «а», только если эта буква существует в «Граница слова» то естьписьмо a внутри «кот» не следует заменять.

Итак, я выполню регулярное выражение (в Питон) как

re.sub("\ba","e", myString.strip()) //заменять a с e

Так что вывод будет e сат eи она eпотрясающий

Я считаю, что ваша проблема связана с тем, что - не является словесным символом.Таким образом, граница слова будет совпадать после -, и поэтому не захватит его.Границы слов совпадают перед первым и после последнего символа слова в строке, а также в любом месте, где перед ним стоит символ слова или несловный символ, а после него — наоборот.Также обратите внимание, что граница слова соответствует нулевой ширине.

Одной из возможных альтернатив является

(?:(?:^|\s)-?)\d+\b

Это будет соответствовать любым числам, начинающимся с пробела и необязательного тире и заканчивающимся границей слова.Он также будет соответствовать числу, начинающемуся с начала строки.

Граница слова \b используется там, где одно слово должно быть словесным символом, а другое - несловным символом.Регулярное выражение для отрицательного числа должно быть

--?\b\d+\b

проверить работу ДЕМО

Я думаю, что это граница (т.символ, следующий за ним) последнего совпадения или начало или конец строки.

когда ты используешь \\b(\\w+)+\\b это означает точное совпадение со словом, содержащим только символы слова ([a-zA-Z0-9])

в вашем случае например настройка \\b в начале регулярного выражения примет -12(с пробелом), но опять не принимает -12(без пробела)

для справки, чтобы поддержать мои слова: https://docs.oracle.com/javase/tutorial/essential/regex/bounds.html

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top