정규 expression
또는 regex
지원은 버전 1.4 이후 자바 플랫폼의 일부가 되어 왔다. java.util.regex
패키지에서 발견되는 regex
클래스는 펄 언어가 제공하는 것과 유사한 패턴 매칭을 지원하지만 자바 언어 구문 및 클래스를 사용한다. 패키지 전체는 Pattern
, Matcher
및 PatternSyntaxException
의 3가지 클래스로 제한된다. 버전 1.5에서는 MatchResult
인터페이스가 소개되었다.
두 클래스 Pattern
및 Matcher
를 함께 사용한다. Pattern
클래스를 사용하여 정규 표현식을 정의한 다음, Matcher
클래스를 사용하여 입력 소스에 대해 패턴을 검사한다. 표현식에서 패턴에 구문 오류가 있으면 예외가 발생한다.
두 클래스 모두 구성자를 가지지 않는다. 대신, 정규 표현식을 컴파일하여 패턴을 얻은 다음 반환된 Pattern
에게 일부 입력 소스를 기반으로 해당 Matcher
를 요청한다.
Pattern pattern = Pattern.compile( <regular expression> );
Matcher matcher = pattern.matcher( <input source> );
Matcher
를 얻었으면 일반적으로 입력 소스를 처리하여 포함된 모든 매칭을 찾는다. find()
메소드를 사용하여 입력 소스에서 패턴의 매칭을 찾는다. find()
에 대한 각 호출은 마지막 호출 위치에서 계속되거나 첫 번째 호출 위치 0에서 계속된다. 그런 다음 매칭되는 항목이 group()
메소드에 의해 반환된다.
while (matcher.find()) {
System.out.printf"Found: \"%s\" from %d to %d.%n",
matcher.group(), matcher.start(), matcher.end());
}
다음 코드는 기본적인 정규 표현식 프로그램을 보여 주며 사용자가 정규 표현식과 비교 대상 문자열을 입력하도록 메시지를 표시한다.
import java.util.regex.*;
public class Regex {
public static void main(String args[]) {
Console console = System.console();
// Get regular expression
String regex = console.readLine("%nEnter expression: ");
Pattern pattern = Pattern.compile(regex);
// Get source
String source = console.readLine("Enter input source: ");
Matcher matcher = pattern.matcher(source);
// Show matches
while (matcher.find()) {
System.out.printf("Found: \"%s\" from %d to %d.%n",
matcher.group(), matcher.start(), matcher.end());
}
}
}
그러면 정규 표현식의 모양은 정확하게 어떠한가? Pattern
클래스는 보다 세부적인 사항을 제공하지만 기본적으로 정규 표현식은 다른 문자 시퀀스와 일치시킬 문자 시퀀스이다. 예를 들어, "Hello, World"
문자열에서 두 개의 L자("ll"
) 문자열 리터럴 패턴을 찾을 수 있다. 앞의 프로그램은 시작 위치 2와 끝 위치 4에서 "ll"
패턴을 찾을 것이다. 끝 위치는 일치된 문자열 패턴의 끝 이후에 다음 문자의 위치이다.
"ll"
같은 패턴 문자열은 입력 소스에서 문자적으로 위치하는 지점만을 보고하므로 그리 흥미롭지 않다. 정규 표현식 패턴은 특수 메타 문자를 포함할 수 있다. 메타 문자는 정규 표현식에서 강력한 매칭 기능을 제공한다. 정규 표현식에서는 "([{\^-$|]})?*+."
의 15문자를 메타 문자로 사용할 수 있다.
일부 메타 문자는 문자 그룹을 나타낸다. 예를 들어, 대괄호([ 및 ]
)를 사용하면 대괄호 안의 문자 중 하나가 텍스트에서 발견되는 경우 매칭이 성공하는 일련의 문자를 지정할 수 있다. 예를 들어, "co[cl]a"
패턴은 coca 및 cola라는 단어와 매칭된다. []
는 단일 문자를 매칭하는 데만 사용되므로 cocla는 매칭되지 않는다. 몇 가지 매칭을 해 보고 문제가 없으면 곧 수량자에 대해 자세히 살펴보자.
개별 문자의 매칭 이외에 대괄호 문자([ 및 ]
)를 사용하여 [j-z]
로 지정된 j-z
의 문자처럼 일정 범위의 문자를 매칭할 수 있다. 이러한 문자 범위는 "foo[j-z]"
처럼 문자열 리터럴과 결합할 수도 있다. 여기서 fool을 찾으면 매칭이 성공하고 food를 찾으면 매칭이 실패한다. l
은 j
와 z
사이의 범위 안에 있지만 d는 그렇지 않기 때문이다. ^
문자를 사용하여 문자열 리터럴 또는 문자 범위의 제외를 나타낼 수도 있다. "foo[^j-z]"
패턴은 foo로 시작하고 j
에서 z
사이의 문자로 끝나지 않는 단어를 찾는다. 따라서 이번에는 food라는 문자열이 매칭에 성공한다. [a-zA-Z]
처럼 여러 범위를 결합하여 a
에서 z
사이의 소문자와 대문자를 나타낼 수도 있다.
정규 표현식을 처음 학습할 때는 문자열 리터럴이 유용하지만 정규 표현식에서 대부분의 사람들이 사용하는 보다 일반적인 요소는 미리 정의된 문자 클래스이다. 여기서 메타 문자 .
및 \
가 사용된다. 마침표(.
)는 임의 문자를 나타내는 데 사용된다. 따라서 정규 표현식 ".oney"
는 money 및 honey와 매칭되며 oney로 끝나는 5
자의 어느 단어와도 매칭된다. 반면에 \
는 다른 문자와 함께 사용되어 전체 문자 집합을 나타낸다. 예를 들어, 숫자 집합을 나타내기 위해 [0-9]
를 사용할 수 있지만 \d
를 사용할 수도 있다. 숫자가 아닌 문자 집합을 나타내기 위해 [^0-9]
를 사용할 수도 있다. 또는 \D
의 미리 정의된 문자 클래스 문자열을 사용할 수 있다. 이러한 모든 문자 클래스 문자열은 모두 기억하기가 어려우므로 패턴 클래스에 대한 자바 플랫폼 문서에 정의되어 있다. 다음은 미리 정의된 특수 문자 클래스의 하위 집합이다.
* \s -- whitespace
* \S -- non-whitespace
* \w -- word character [a-zA-Z0-9]
* \W -- non-word character
* \p{Punct} -- punctuation
* \p{Lower} -- lowercase [a-z]
* \p{Upper} -- uppercase [A-Z]
미리 정의된 문자열과 관련하여 지적해야 할 사항은 즉각 눈에 띄지 않는다. 위의 Regex
프로그램에 이러한 문자열 중 하나를 사용하려면 표시된 대로 입력한다. \s
는 공백과 매칭된다. 하지만 자바 소스 파일에서 정규 표현식을 하드 코딩하려면 \
문자가 특별하게 취급된다는 것을 기억해야 한다. 소스에서 이 문자열을 다음과 같이 이스케이프해야 한다.
String regexString = "\\s";
여기서 \\
는 문자열에서 하나의 백슬래시를 나타낸다. 다른 문자열 리터럴을 나타내기 위한 기타 특수 문자열은 다음과 같다.
* \t -- tab
* \n -- newline
* \r -- carriage return
* \xhh -- hex character 0xhh
* \uhhhh -- hex character 0xhhhh
수량자는 정규 표현식을 더욱 흥미롭게 만드는데 문자 클래스 같은 기타 표현식과 결합될 때는 특히 그렇다. 예를 들어, a-z
에서 3자의 문자열을 매칭하기 위해 "[a-z][a-z][a-z]"
패턴을 사용할 수도 있지만 그럴 필요가 없다. 문자열을 반복하는 대신 패턴 다음에 수량자를 추가하면 된다. 이 예제의 경우, "[a-z][a-z][a-z]"
는 ":[a-z]{3}"
으로 나타낼 수 있다. 특정 수량에 대해 숫자가 {}
괄호 안에 들어간다. ?, * 또는 +
문자를 사용하여 0번 또는 한 번, 0번 이상, 한 번 이상을 각각 나타낼 수도 있다.
[a-z]?
패턴은 a-z
의 문자와 0번 또는 한 번 매칭된다. [a-z]*
패턴은 a-z
의 문자와 0번 이상 매칭된다. [a-z]+
패턴은 a-z
의 문자와 한 번 이상 매칭된다.
수량자는 주의해서 사용한다. 0번 매칭을 허용하는 수량자에는 특별한 주의를 기울여야 한다.
괄호 기호({}
)를 수량자로 사용할 때는 범위를 지정해야 한다. {3}
은 정확히 3
번을 의미하지만 {3,}
은 적어도 3
번을 의미한다. 수량자 {3, 5}
는 3
번에서 5
번까지의 패턴과 매칭된다.
정규 표현식에는 여기서 살펴본 것보다 훨씬 많은 내용이 있다. 특정 상황에 맞는 정규 표현식을 사용하는 것이 중요하다. 앞의 Regex 프로그램을 사용하여 몇 가지 표현식을 시험해 보고 기대했던 결과가 나오는지 확인해 본다. 여러 가지 수량자를 사용하여 각 차이가 어떻게 나오는지 이해할 수 있도록 한다. 일반적으로 수량자는 가능한 매칭에 대해 최대 수의 문자를 포함하려고 한다.
정규 표현식에 대한 자세한 내용을 살펴보려면 자바 온라인 자습서의 정규 표현식 편을 참고한다.
또한 패턴 클래스에 대한 내용은 javadoc을 참고한다.
"Java SE" 카테고리의 다른 글
- Java2D 소프트 클리핑 (댓글 6개 / 트랙백 0개) 2006/10/24
- JDESKTOP NETWORK COMPONENTS (JNDC)를 이용한 테이블 소개 (댓글 2개 / 트랙백 0개) 2005/05/31
- 가변 arity 메소드 (댓글 1개 / 트랙백 2개) 2005/11/15
- 스플래시 스크린과 MUSTANG (댓글 1개 / 트랙백 1개) 2005/12/20
- 제네릭(GENERIC) (댓글 3개 / 트랙백 1개) 2005/05/10
- 향상된 루프문 (댓글 2개 / 트랙백 1개) 2005/07/04
- HOTSPOT 가비지 콜렉션 구성 옵션 (댓글 3개 / 트랙백 0개) 2005/04/12
- 스윙 "괴담" (댓글 1개 / 트랙백 0개) 2005/09/13
- TIMEZONE CLASS이용하기 (댓글 2개 / 트랙백 2개) 2003/11/04
- 리스너 리스트를 위한 WEAKHASHMAP 사용하기 (댓글 1개 / 트랙백 0개) 2006/03/08