2015-10-15 1 views
2

следующий код:Странное поведение с обнаружением конкретных puntucations в регулярных выражениях

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 


public class Main { 

public static void main(String[] args) { 
    // TODO Auto-generated method stub 

      // Create a Pattern object 
      Pattern r = Pattern.compile("[?:!.,;'’\"“”«»<>=()_-]+"); 

      // Now create matcher object. 
      Matcher m = r.matcher("Hello,World!"); 

      while(m.find()) 
      System.out.println(m.group()); 

     } 
} 

выходы:

, 
! 

Если добавить знаки препинания - в регулярных выражений (более дефиса), так что она становится:

Pattern r = Pattern.compile("[?:!.,;'’\"“”«»<>=()_-–]+"); 

выход становится:

ello, 
orld! 

Кто-нибудь может сказать мне, почему эта странная неисправность?

+3

Поскольку этот символ '-' действует как диапазон от' _' до длинного дефиса –

+3

'Pattern r = Pattern.compile (" [?:!.,; '' \ "" "« »<> = () _--] + ");' Обязательно сохраните '-' в первой или последней позиции в классе символов. – anubhava

ответ

4

Это из-за приборной панелью (-) между _ и который создает диапазон, и включает в себя все символы Unicode, чьи кодовые находятся между _ и .

  • _ является U + 005F
  • является U + 2013

Так что все в промежутке между входит в диапазон. Сюда входят латинские буквы нижнего регистра (они варьируются от U + 0061 до U + 007A).

Верхние латинские буквы от U + 0041 до U + 005A и поэтому расположены до подчеркивание в U + 005F. Они исключаются из класса символов.

Поместите тире в начале или в конце класса символов, чтобы исправить проблему.

[?:!.,;'’\"“”«»<>=()_–-]+ 

В качестве альтернативы, вы могли бы избежать его с помощью обратной косой черты, но я бы посоветовал вам придерживаться первого/последнего правила, как это легче читать.

1

Некоторые основы Класс:

Все регулярные выражения специальные символы могут быть экранированы вне классов, так что
его буквальный смысл вызывается.

Внутренние классы, на первый взгляд, символ ASCII тире - является диапазон оператор
который вы помните.

Чтобы вызвать его буквальное значение, его можно разместить в начале или конце класса
.

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

Разбор одного символа слева направо, один символ представляет
влево. Если тире находится следующий символ, следующий символ
представляет собой правильную позицию.Это представляет собой простой диапазон
построить внутри классов.

Все, что находится за пределами этой конструкции, тире является буквальным.

Например [a-c-m-o] представляют собой, B, C, M, N, O, и -

Так, тире в начале или в конце концов, не может быть разобран как оператор диапазона,
ни, если это между диапазонами или справа от одного (пример: [a-d-tovz]).
Конечно, в начале или в конце его проще
быть уверенным, что он не используется в качестве оператора дальности.

Как всегда, что-либо, спрятанное в классе, рассматривается как литерал, свойство или
управляющий код.

Кроме того, свойства не могут быть левой/правой стороной конструкции диапазона.

Java имеет некоторые другие специальные конструкции класса, такие как операторы союзов и
вложенных классов, но я думаю, что функциональность оператора диапазон в основном
одинакова для всех двигателей.

Смежные вопросы