Как бы вы перевели это регулярное выражение Perl на Java?
/pattern/i
Вы не можете.
Есть много причин для этого. Вот некоторые из них:
Java не поддерживает столь выразительный язык регулярных выражений, как Perl. В нем отсутствует поддержка графем (например, \X)
и полная поддержка свойств (например, \p{Sentence_Break=SContinue}
), отсутствуют имена с именами Юникод, нет оператора сброса ветви (?|...|...|)
, нет именованных групп захвата или логического \x{...}
бежать до Java 7, не имеет рекурсивных регулярных выражений и т. д. и т. д. и т. д. Я мог бы написать книгу о том, чего здесь не хватает в Java: привыкнуть возвращаться к очень примитиву и неудобно использовать движок regex по сравнению с к чему ты привык.
Еще одна проблема еще хуже, потому что у вас есть похожие faux amis вроде \w
и и \b
и \s
, и даже \p{alpha}
и \p{lower}
, которые ведут себя по-разному в Java по сравнению с Perl; в некоторых случаях версии Java совершенно непригодны и содержат ошибки. Это потому, что Perl следует UTS # 18 , но до Java 7 Java не делал. Вы должны добавить флаг UNICODE_CHARACTER_CLASSES
из Java 7, чтобы они перестали нарушаться. Если вы не можете использовать Java 7, откажитесь сейчас, потому что в Java было много-много других ошибок Unicode до Java 7, и с этим просто не стоит бороться с ними.
Java обрабатывает разрывы строк через ^
и $
и .
, но Perl ожидает, что разрывы строк в Unicode будут \R
. Вы должны посмотреть на UNIX_LINES
, чтобы понять, что там происходит.
По умолчанию Java не применяет никаких регистров Unicode вообще. Обязательно добавьте флаг UNICODE_CASE
к вашей компиляции. В противном случае вы не получите такие вещи, как различные греческие сигмы, совпадающие друг с другом.
Наконец, все по-другому, потому что в лучшем случае Java выполняет только простое свертывание, тогда как Perl всегда делает полное сведение. Это означает, что вы не получите \xDF
для сопоставления с регистром "SS", нечувствительным к Java, и с аналогичными проблемами.
В итоге, самое близкое, что вы можете получить, это скомпилировать с флагами
CASE_INSENSITIVE | UNICODE_CASE | UNICODE_CHARACTER_CLASSES
, что эквивалентно встроенному "(?iuU)"
в строке шаблона.
И помните, что совпадение в Java не означает совпадение, достаточно извращенно.
EDIT
А вот и остальная часть истории ...
Во время компиляции он не соответствует "PattErn" для меня, он не работает
Pattern p = Pattern.compile("/pattern/i");
Matcher m = p.matcher("PattErn");
System.out.println(m.matches()); // prints "false"
У вас не должно быть косых черт вокруг шаблона.
Лучшее, что вы можете сделать, это перевести
$line = "I have your PaTTerN right here";
if ($line =~ /pattern/i) {
print "matched.\n";
}
таким образом
import java.util.regex.*;
String line = "I have your PaTTerN right here";
String pattern = "pattern";
Pattern regcomp = Pattern.compile(pattern, CASE_INSENSITIVE
| UNICODE_CASE
// comment next line out for legacy Java \b\w\s breakage
| UNICODE_CHARACTER_CLASSES
);
Matcher regexec = regcomp.matcher(line);
if (regexec.find()) {
System.out.println("matched");
}
Вот, посмотри, насколько это проще? :)
Еще одна вещь, которую вы теряете с Java, потому что Java на самом деле не знает регулярное выражение из двусвязного списка из дыры в его голове, это компиляция шаблонов во время компиляции. Я, я всегда нашел время компиляции лучшим временем для компиляции, но попробуйте рассказать об этом Java. В Java очень сложно осознать эту очень простую меру здравомыслия программы, то, что вам действительно нужно постоянно делать в каждой программе. Этот недостаток дизайна - королевская боль в заднице, потому что в середине вашей программы вы делаете исключение для чего-то, что должно было быть обнаружено во время компиляции, когда остальная часть вашей программы компилировалась. Примерно так же раздражительно, как и прерывание полового акта, потому что вы были на пути к тому, чтобы завершить свой бизнес, и BANG все разрушено.
Я не реализовал решение этой досадной досады в моем коде выше, но вы можете подделать его с некоторой статической инициализацией.