ILoveCoffee, ILoveJava

java.util.regex.Pattern 설명 (Regular Expression > Methods of the Pattern Class)

jeeyong 2011. 12. 19. 17:00
지금까지 우리는 test harness를 이용하여 패턴 객체를 생성하고 그들의 기본 폼을 이용하였다. 이번 섹션에서는 좀더 향상된 기술로 플래그와 함깨 패턴을 생성하거나 포함된 플래그 표현들을 이용할 것이다. 우리가 아직 논의하지 않은 몇가지 유용한 추가적인 내용들에 대해서 논의할 것이다.

Creating a Pattern with Flags

Pattern 클래스는 플래그를 제공하는 새로운 compile 메소드를 가지고 있다. 플래그 파라미터는 비트 마스크 처리가 되며 다음과 같이 public static field들로 구성되어 잇다.
  • Pattern.CANON_EQ 규칙에 의해서 같은지 검사하도록 한다. 이 플래그가 지정되면 2개의 캐릭터는 매치를 수행할때 전체가 규칙에 의해서 분해를 수행한 것이 매칭이 되는지 고려하여 검사를 수행한다. 표현식을 "a\u030A"로 지정했다면 이것은"\u00E5"와 매치가 수행될 것이다. 기본값은 canonical equivalence를 수행하지 않는 방향으로 되어 있다. 이 플래그는 성능상에 문제를 일으킨다.

  • Pattern.CASE_INSENSITIVE 대소문자 구분을 하는 매치를 수행한다. 기본적으로 US-ASCII에 한해서 대소문자 구분이 기본값으로 지정되어 있다. 유니코드의 경우 특정 UNICODE_CASE 플래그에 의해서 케이스를 고려하여 매치를 수행한다. Case-insensitive 매치 역시 가능하며, 이것은 표현식을 내장 플래그인 ?i로 지정함으로 해서 가능하다. 이 플래그가 지정하면 작은 성능상의 패널티가 있다.

  • Pattern.COMMENTS 패턴에서 공백과 코멘트를 허용할지 결정한다. 이 모드에서는 whitespace는 무시되고, #로 시작하는 커멘트는 무시된다. 코멘트 모드는 내장 플래그인 표현식 (?x)로 지정이 가능하다.

  • Pattern.DOTALL dotall 모드를 가능하게 한다. dotall 모드에서 표현식 . 은 어떠한 문자든이란 의미로 매칭된다. 마침 문자까지 합쳐서 말이다. 기본 표현식으로는 라인 종료 문자는 매치가 되지 않는다. Dotall 모드는 내장 플래그인 (?s)를 지정해서 이용할 수 있다. 이 s는 부호 표시로, 단일 라인을 위한 모드이다. 이것은 Perl에서 이러한 내용을 처리하고 있다.

  • Pattern.LITERAL 패턴의 리터럴 파싱을 가능하게 한다. 이 플래그를 설정하면 입력되는 문자에 대해서 특정 문자가 literal 문자의 시퀀스로 다룰수 있게 한다. 입력 시퀀스에서 메타 문자 혹은 이스케이프 시퀀스는 특별한 의미를 가지지 않는다. 이 플래그는 CASE_INSENSITIVE와 UNICODE_CASE와 같이 이용할 수 있다. 다른 플래그는 동작하지 않는다. 이것은 내장 플래그가 없다.

  • Pattern.MULTILINE 멀티라인 모드를 지원한다. 멀티라인 모드는 ^와 $ 매핑에서 이용되며, 입력 시퀀스가 끝이 나거나, 종료문자가 나올때 까지 처리가 된다. 기본적으로 이 표현은 입력 시퀀스의 시작에서 전체 문자를 매치할때 주로 이용된다. 멀티라인 모드는 내장 플래그 (?m)을 이용하여 적용가능하다.

  • Pattern.UNICODE_CASE 유니코드 대소문자 처리를 수행할 수 있도록 한다. 이 플래그를 설정하면 case-insensitive 매칭대신에 CASE_INSENSITIVE 플래그를 동일한 방법으로 Unicode 표준에 적용할 수 있게 된다. 기본적으로 case-insensitive 매치는 US-ASCII 문자셋에서 이용된다. 유니코드 모드는 내장 플래그이 (?u)를 이용할 수 있으며 이 플래그를 지정하면 성능상 패널티가 있다.

  • Pattern.UNIX_LINES 유닉스의 라인 모드를 가능하게 한다. 이 모드는 '\n' 라인 터미네이터만 ., ^, $의 역할을 수행하도록 하게 한다. 유닉스 라인 모드는 내장 플래그인 (?d)를 이용할 수 있다.
다음 단계에서는 test harness를 case-insensitive 매칭 패턴으로 생성하게끔 수정할 것이다.

First, modify the code to invoke the alternate version of compile

Pattern pattern =

Pattern.compile(console.readLine("%nEnter your regex: "), Pattern.CASE_INSENSITIVE);

이 코드를 컴파일 하고 실행해보면 다음과 같은 결과가 나온다.
Enter your regex: dog

Enter input string to search: DoGDOg

I found the text "DoG" starting at index 0 and ending at index 3.

I found the text "DOg" starting at index 3 and ending at index 6.
보는바와 같이 "dog"라는 문자 리터럴은 케이스를 무시하고 매치를 수행한다. 멀티플 플래그와 비트 OR 연산을 수행할 수 있다. 명확하게 다음 샘플 코드는 콘솔로 정규식을 읽어들이는 것이 아니라. 하드코딩 하는것을 볼 수 있다.
pattern = Pattern.compile("[az]$", Pattern.MULTILINE | Pattern.UNIX_LINES);
또한 정수형 값을 세팅할 수도 있다.
final int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;

Pattern pattern = Pattern.compile("aa", flags);

Embedded Flag Expressions

우리는 embeded flag expression을 이용하여 다양한 플래그를 지정할 수 있다. Embedded flag 표현은 compile의 서로다른 아규먼트를 다양하게 받을 수 있도록 할 수 있도록 한다. 다음 예제는 원본 test harness이다. 이것은 내장 플래그 표현식(?i)를 이용하여 case-insensitive 매칭을 수행하는 예이다.
Enter your regex: (?i)foo

Enter input string to search: FOOfooFoOfoO

I found the text "FOO" starting at index 0 and ending at index 3.

I found the text "foo" starting at index 3 and ending at index 6.

I found the text "FoO" starting at index 6 and ending at index 9.

I found the text "foO" starting at index 9 and ending at index 12.
보면 모든 매칭을 case에 상관없이 수행하고 있다는것을 알 수 있다.

embedded flag 표현식은 Pattern's의 다음 테이블과 같이 대응됨을 확인할 수 있다.

 Constant  Equivalent Embedded Flag Expression
 Pattern.CANON_EQ  None
 Pattern.CASE_INSENSITIVE  (?i)
 Pattern.COMMENTS  (?x)
 Pattern.MULTILINE  (?m)
 Pattern.DOTALL  (?s)
 Pattern.LITERAL  None
 Pattern.UNICODE_CASE  (?u)
 Pattern.UNIX_LINES  (?d)

Using the matches(String,CharSequence) Method

Pattern 클래스는 matches 메소드를 이용하여 주어진 입력 문자에서 특별한 패턴을 빠르게 체크할 수 있는 편리함을 제공한다. 모든 public static 메소드와 같이 matches 메소드를 호출할 수있다. 이것은 Pattern.matches("\\d","1");와 같이 이용할 수 있다. 이 예에서는 메소드는 true를 반환한다. 왜냐하면 "1"이라는 숫자는 정규식 \d에 매칭되기 때문이다.

Using the split(String) Method

split메소드는 텍스트를 패턴과 매칭시켜 나눌어 모을 수 있는 대단한 툴이다. 아래와 같이 SplitDemo.java에서는 split 메소드를 이용하여 "one two three four five"를 "one:two:three:four:five"에서 추출하는 처리를 수행한다.
import java.util.regex.Pattern;

import java.util.regex.Matcher;



public class SplitDemo {



private static final String REGEX = ":";

private static final String INPUT = "one:two:three:four:five";



public static void main(String[] args) {

Pattern p = Pattern.compile(REGEX);

String[] items = p.split(INPUT);

for(String s : items) {

System.out.println(s);

}

}

}


OUTPUT:
one

two

three

four

five
단순하게 우리는 스트링 문자를 colon(:)로 복잡한 정규식 문자를 대신하고 있다. 우리가 사용한 Pattern과 Matcher 객체를 여전히 이용할 수 있따. 그리고 이렇나 정규식을 통해서 텍스트를 나눌 수 있다. 여기에는 SplitDemo2.java와 같이 split를 수정하여 처리하는 예를 보여준다.

import java.util.regex.Pattern;

import java.util.regex.Matcher;



public class SplitDemo2 {



private static final String REGEX = "\\d";

private static final String INPUT = "one9two4three7four1five";



public static void main(String[] args) {

Pattern p = Pattern.compile(REGEX);

String[] items = p.split(INPUT);

for(String s : items) {

System.out.println(s);

}

}

}

OUTPUT:
one

two

three

four

five


Other Utility Methods

다음 메소드를 찾아보고 이용해보자.
  • public static String quote(String s) 지정된 문자를 위해서 리터럴 패턴을 반환한다. 이 메소드는 해당하는 문자에서 매치되는 문자 s를 찾기 위한 패턴을 찾아준다. 메타문자 혹은 이스케이프 시퀀스가 반환된다.

  • public String toString() 이 패턴의 표현식을 반환한다. 이것은 정규식 표현으로 부터 컴파일된 패턴을 반환한다.

Pattern Method Equivalents in java.lang.String

정규식 표현은  java.lang.String을 통해서 몇몇 메소드에서 이용하고 있으며, java.util.regex.Pattern의 행동을 모사하고 있다. 편의상 아래와 같이 표현해보면 다음과 같다.
  • public boolean matches(String regex): 주어진 정규식 표현이 매치가 되는지 검사한다. 이 메소드를 호출하면 str.matches(regex)의 결과는 정확하게 Pattern.matches(regex,str)과 동일하게 처리된다.

  • public String[] split(String regex, int limit): 주어진 정규식을 이용하여 매치되는 문자단위라 잘라낸다. 이 메소드를 호출하는것은 str.split(regex, n)으로 지정할 수 있으며 이것의 결과는 Pattern.compile(regex).split(str, n)과 동일한 결과는 반환한다.

  • public String[] split(String regex): 주어진 정규식에 매치되는 문자를 반환하고, 두개의 아규먼트를 주는 이전 메소드에서 limit를 0으로 주는것과 동일한 결과를 낸다. 결과 배열에서 공백 문자는 포함되지 않는다.
또한 replace 메소드를 하나의 CharSequence에서  처리를 수행할 수 있다.

'ILoveCoffee, ILoveJava' 카테고리의 다른 글

java 정렬 알고리즘  (0) 2012.12.03
Calendar 객체에서 주, 요일(일~토)를 이용한 날짜 변환  (2) 2012.05.29
OAuth  (1) 2010.07.16
java의 synchronized 분석  (0) 2010.07.14
java:comp/env  (0) 2009.02.24