Почему \ S + с границами не извлекает непространственные символы? [Дубликат]

Java имеет пул строк, в котором Java управляет распределением памяти для объектов String. См. String Pools в Java

Когда вы проверяете (сравниваете) два объекта с помощью оператора ==, он сравнивает равенство адресов в пуле строк. Если два объекта String имеют одинаковые адреса, то он возвращает true, в противном случае false. Но если вы хотите сравнить содержимое двух объектов String, вы должны переопределить метод equals.

equals - фактически метод класса Object, но он переопределяется в класс String и дается новое определение, которое сравнивает содержимое объекта.

Example:
    stringObjectOne.equals(stringObjectTwo);

Но помните, что это относится к случаю String. Если вы хотите сравнить регистр без учета регистра, вы должны пойти для метода equalsIgnoreCase класса String.

Давайте посмотрим:

String one   = "HELLO"; 
String two   = "HELLO"; 
String three = new String("HELLO"); 
String four  = "hello"; 

one == two;   // TRUE
one == three; // FALSE
one == four;  // FALSE

one.equals(two);            // TRUE
one.equals(three);          // TRUE
one.equals(four);           // FALSE
one.equalsIgnoreCase(four); // TRUE

74
задан Wiktor Stribiżew 25 October 2017 в 17:11
поделиться

10 ответов

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

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

56
ответ дан Gilles 17 August 2018 в 09:06
поделиться
  • 1
    Correctamundo. \b - утверждение с нулевой шириной, которое соответствует, если есть \w с одной стороны, и либо есть \W на другом, либо позиция начинается или заканчивается. \w произвольно определяется как «идентификатор», символы (alnums и подчеркивание), а не что-то особенно полезное для английского языка. – hobbs 24 August 2009 в 22:02
  • 2
    100% правильно. Извиняюсь за то, что вы просто не комментируете свои слова. Я попал в submit, прежде чем увидел ваш ответ. – Brent Writes Code 24 August 2009 в 22:05
  • 3
    для понимания, можно ли переписать регулярное выражение \bhello\b без использования \b (используя \w, \W и другие)? – David Portabella 28 September 2016 в 09:40
  • 4
    Сортировка: (^|\W)hello($|\W), за исключением того, что он не будет захватывать любые символы без слова до и после, поэтому он будет больше похож на (^|(?<=\W))hello($|(?=\W)) (с помощью утверждений lookahead / lookbehind). – brianary 28 September 2016 в 09:58
  • 5
    @brianary Немного проще: (?<!\w)hello(?!\w). – David Knipe 19 November 2017 в 18:16

Я столкнулся с еще более серьезной проблемой при поиске текста для таких слов, как .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/ , без которой мир регулярных выражений был бы очень несчастным!

4
ответ дан Alan Moore 17 August 2018 в 09:06
поделиться
  • 1
    Я изо всех сил пытался понять, почему я не мог сопоставить C#, но теперь это яснее – Mugoma J. Okomba 6 December 2016 в 20:48
  • 2
    Это лучшее объяснение. – Chris Leung 7 February 2018 в 07:47

Проверьте документацию по граничным условиям:

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 вроде бы избил меня до удара, так что он получает голосование.

4
ответ дан Brent Writes Code 17 August 2018 в 09:06
поделиться

Я говорю о том, что [r2] -строчные границы регулярных выражений на самом деле здесь .

Короче говоря, они условны. Их поведение зависит от того, к чему они относятся.

# same as using a \b before:
(?(?=\w) (?<!\w)  | (?<!\W) )

# same as using a \b after:
(?(?<=\w) (?!\w)  | (?!\W)  )

Иногда это не то, что вы хотите. См. Мой другой ответ для разработки.

4
ответ дан Community 17 August 2018 в 09:06
поделиться

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

Возможна одна из возможных альтернатив

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

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

1
ответ дан Sean 17 August 2018 в 09:06
поделиться

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

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

0
ответ дан snr 17 August 2018 в 09:06
поделиться

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

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

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

17
ответ дан SongWithoutWords 17 August 2018 в 09:06
поделиться

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

0
ответ дан user 17 August 2018 в 09:06
поделиться
  • 1
    Вы думаете об \G: соответствует началу строки (например, \A) при первой попытке совпадения; после этого он соответствует позиции, в которой закончился предыдущий матч. – Alan Moore 24 June 2016 в 20:50

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

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

для ссылки на мои слова: https://docs.oracle.com/javase/tutorial/essential/ регулярное выражение / bounds.html

0
ответ дан vic 17 August 2018 в 09:06
поделиться
4
ответ дан Alan Moore 6 September 2018 в 06:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: