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
Граница слов в большинстве диалектов регулярных выражений - это позиция между \w
и \W
(неглавным символом) или в начале или конце строки, если она начинается или заканчивается (соответственно) словом ([0-9A-Za-z_]
).
Итак, в строке "-12"
она будет соответствовать до 1 или после 2. Черточка не является символом слова.
Я столкнулся с еще более серьезной проблемой при поиске текста для таких слов, как .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/ , без которой мир регулярных выражений был бы очень несчастным!
C#
, но теперь это яснее
– Mugoma J. Okomba
6 December 2016 в 20:48
Проверьте документацию по граничным условиям:
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 вроде бы избил меня до удара, так что он получает голосование.
Я говорю о том, что [r2] -строчные границы регулярных выражений на самом деле здесь .
Короче говоря, они условны. Их поведение зависит от того, к чему они относятся.
# same as using a \b before:
(?(?=\w) (?<!\w) | (?<!\W) )
# same as using a \b after:
(?(?<=\w) (?!\w) | (?!\W) )
Иногда это не то, что вы хотите. См. Мой другой ответ для разработки.
Я считаю, что ваша проблема связана с тем, что -
не является символом слова. Таким образом, граница слова будет соответствовать после -
, и поэтому ее не будет захватывать. Границы слов совпадают перед первым и после последнего слова в строке, а также в любом месте, где перед символом слова или символом, отличным от слова, и после того, как это будет наоборот. Также обратите внимание, что граница слова является совпадением по нулевой ширине.
Возможна одна из возможных альтернатив
(?:(?:^|\s)-?)\d+\b
. Это будет соответствовать любым номерам, начинающимся с символа пробела и необязательной тире, и заканчивая на границе слова. Он также будет соответствовать числу, начинающемуся в начале строки.
В процессе изучения регулярного выражения я действительно застрял в метасимволе, который есть \b
. Я действительно не понимал его смысла, когда я спрашивал себя «, что это такое, что это » повторяется. После некоторых попыток с помощью веб-сайта , я смотрю розовые вертикальные черточки в каждом начале слов и в конце слов. В то время я хорошо это понял. Теперь это точно слово (\w
) - граница.
Мое мнение - просто для понимания, ориентированного на понимание. Логику его следует изучить из других ответов.
Граница слов может встречаться в одной из трех позиций:
Символы Word являются буквенно-цифровыми; знак минус - нет. Взято из Учебник по регулярному выражению .
Я думаю, что это граница (т. е. символ) последнего совпадения или начало или конец строки.
\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
\b
- утверждение с нулевой шириной, которое соответствует, если есть\w
с одной стороны, и либо есть\W
на другом, либо позиция начинается или заканчивается.\w
произвольно определяется как «идентификатор», символы (alnums и подчеркивание), а не что-то особенно полезное для английского языка. – hobbs 24 August 2009 в 22:02\bhello\b
без использования\b
(используя\w
,\W
и другие)? – David Portabella 28 September 2016 в 09:40(^|\W)hello($|\W)
, за исключением того, что он не будет захватывать любые символы без слова до и после, поэтому он будет больше похож на(^|(?<=\W))hello($|(?=\W))
(с помощью утверждений lookahead / lookbehind). – brianary 28 September 2016 в 09:58(?<!\w)hello(?!\w)
. – David Knipe 19 November 2017 в 18:16