В чем разница между \ z и \ Z в регулярном выражении и когда и как его использовать? - PullRequest
34 голосов
/ 25 апреля 2010

С http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html:

\Z  The end of the input but for the final terminator, if any
\z  The end of the input

Но что это означает на практике? Можете ли вы привести пример, когда я использую \ Z или \ z.

В моем тесте я думал, что "StackOverflow\n".matches("StackOverflow\\z") вернет true, а "StackOverflow\n".matches("StackOverflow\\Z") вернет false. Но на самом деле оба возвращают false. Где ошибка?

Ответы [ 5 ]

33 голосов
/ 25 апреля 2010

Даже если \Z и $ совпадают только в конце строки (когда вариант для каретки и доллара, чтобы соответствовать во встроенных переносах строки выключено), есть одно исключение. Если строка заканчивается разрывом строки, тогда \Z и $ будут совпадать в позиции до разрыва строки, а не в самом конце строки.

Это "улучшение" было введено Perl и скопировано многими регулярными выражениями вкусы, включая Java, .NET и PCRE. В Perl при чтении строки из файла результирующая строка оканчивается переводом строки. чтение строка из файла с текстом "joe" приводит к строке joe \ n. При применении к этой строке оба параметра ^[a-z]+$ и \A[a-z]+\Z будут соответствует "Джо".

Если вы хотите найти совпадение только в самом конце строки, используйте \z (строчная буква z вместо прописной буквы Z). \A[a-z]+\z не соответствовать Джо \ n. \z соответствует после разрыва строки, что не соответствует по классу персонажей.

http://www.regular -expressions.info / anchors.html

То, как я прочитал это "StackOverflow\n".matches("StackOverflow\\z"), должно возвращать false, потому что ваш шаблон не включает перевод строки.

"StackOverflow\n".matches("StackOverflow\\z\\n") => false
"StackOverflow\n".matches("StackOverflow\\Z\\n") => true
5 голосов
/ 25 апреля 2010

Только что проверил. Похоже, что когда Matcher.matches () вызывается (как в вашем коде, за кадром), \ Z ведет себя как \ z. Однако при вызове Matcher.find () они ведут себя иначе, чем ожидалось. Следующее возвращает true:

Pattern p = Pattern.compile("StackOverflow\\Z");
Matcher m = p.matcher("StackOverflow\n");
System.out.println(m.find());

и если заменить \ Z на \ z, возвращается false.

Я нахожу это немного удивительным ...

0 голосов
/ 31 мая 2017

\Z совпадает с $, соответствует концу строки, после конца строки может следовать разрыв строки.

enter image description here enter image description here

\z соответствует концу строки, не может сопровождаться переводом строки.

enter image description here enter image description here

0 голосов
/ 27 мая 2016

Я думаю, что главная проблема здесь заключается в неожиданном поведении matches(): любое совпадение должно потреблять всю входную строку . Оба ваших примера терпят неудачу, потому что регулярные выражения не потребляют перевод строки в конце строки. Якоря не имеют к этому никакого отношения.

В большинстве языков совпадение с регулярным выражением может происходить где угодно, потребляя всю, некоторую часть или ни одну из входной строки. И у Java есть метод Matcher#find(), который выполняет это традиционное соответствие. Однако результаты противоположны тому, что вы сказали, что ожидали:

Pattern.compile("StackOverflow\\z").matcher("StackOverflow\n").find()  //false
Pattern.compile("StackOverflow\\Z").matcher("StackOverflow\n").find()  //true

В первом примере \z должен соответствовать концу строки, но конечный перевод строки не выполняется. Во втором * \Z совпадает до перевода строки, который находится в конце строки.

0 голосов
/ 25 апреля 2010

Как сказал Eyal, он работает для find (), но не для match ().

Это действительно имеет смысл. Сам якорь \ Z действительно соответствует позиции непосредственно перед конечным терминатором eol, но регулярное выражение в целом не совпадает, потому что, в целом, оно должно соответствовать всему сопоставляемому тексту, и ничто не соответствует терминатору. (\ Z соответствует позиции справа перед терминатором, что не одно и то же.)

Если вы сделали "StackOverflow\n".matches("StackOverflow\\Z.*"), с вами все будет в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...