어플리케이션들을 만들다 보면 종종 단어 검색, 메일 주소 점검, XML 문서의 무결성 확인 등과 같은 복잡한 문자열 처리 기능이 필요한 경우가 있게 마련이다. 이런 때에 패턴 매칭(pattern matching)이 자주 사용된다. Perl과 sed, awk와 같은 언어들은 일치하는 텍스트를 검색하기 위해, 패턴을 정의하는 문자들과 정규표현식을 사용해 향상된 패턴 매칭 능력을 제공해 주고 있다. 자바에서 패턴 매칭을 사용하려면 StringTokenizer 클래스와 수많은 charAt, substring 메소드를 동원해야만 한다. 하지만 이런 방식은 종종 아주 복잡하고 지저분한 코드를 만들어내곤 한다.
하지만모두지금까지의이야기일뿐Java 2 Platform, Standard Edition(J2SE)가1.4로넘어오면서정규표현식을다룰수있는java.util.regex라는새로운패키지가추가되었다.이제자바에도정규표현식의강력함을맛볼수있는메타캐릭터들을사용할수있게되었다.
이번글에서는정규표현식에대해간단히설명하고,아래의과정에따라java.util.regex패키지를통해정규표현식을활용하는방법에대해자세히설명하도록하겠다.
l 단어바꾸기
l 메일주소점검
l 파일에서제어문자제거
l 파일검색
(이글의예제들을실행시켜보려면J2SE 1.4호환컴파일러와가상머신이필요함)
정규표현식만들기
정규표현식이란여러문자열들의공통적인특성을기술하는문자들의패턴이다. java.util.regex패키지를보면입력데이터로부터패턴을찾고수정할수있는다양한방법들이제공됨을확인할수있을것이다.
정규표현식의가장단순한형태는‘Java’, ‘programming’과같은일반적인문자열이다.또한메일주소와같이특수한포맷을갖는문자열을검증등도가능하다.
정규표현식에는일반문자들과특수문자들이혼용되어사용된다.
\$ |
^ |
. |
* |
+ |
? |
[‘ |
‘] |
\. |
|
|
|
‘\’로시작하는문자열을제외한모든문자들은보통문자를의미한다.
특수문자들은물론고유한기능을갖고있다.예를들어‘.’의경우라인종결문자를제외한어떤문자와도대응될수있다.따라서정규표현식‘s.n’은‘sun’, ‘son’등과같이‘s’로시작하고‘n’으로끝나는세자로된문자열어떤것이든될수있다.
이와같이우리는정규표현식에서제공되는여러특수문자들을통해줄의시작단어를찾거나,특정범위의문자찾기,대소문자구별없이찾기,정확히일치하는단어찾기등의작업을쉽게처리할수있다.
java.util.regex패키지에서제공하는정규표현식은Perl언어에서의정규표현식사용법과같기때문에Perl에익숙한사용자라면같은문법을그대로자바에도적용할수있다.만약정규표현식에익숙하지않다면아래표가많은도움이될것이다.
Construct |
Matches |
Characters |
|
X |
The characterx |
\\ |
The backslash character |
\0n |
The character with octal value0n(0 <= n <= 7) |
\0nn |
The character with octal value0nn(0 <= n <= 7) |
\0mnn |
The character with octal value0mnn(0 <= m <= 3, 0 <= n <= 7) |
\xhh |
The character with hexadecimal value 0xhh |
\uhhhh |
The character with hexadecimal value 0xhhhh |
\t |
The tab character ('\u0009') |
\n |
Thenewline(line feed) character ('\u000A') |
\r |
The carriage-return character ('\u000D') |
\f |
The form-feed character ('\u000C') |
\a |
The alert (bell) character ('\u0007') |
\e |
The escape character ('\u001B') |
\cx |
The control character corresponding tox |
|
|
Character Classes | |
[abc] |
a,b, orc(simple class) |
[^abc] |
Any character excepta,b, orc(negation) |
[a-zA-Z] |
athroughzorAthroughZ, inclusive (range) |
[a-z-[bc]] |
athroughz, except forbandc:[ad-z](subtraction) |
[a-z-[m-p]] |
athroughz, except formthroughp:[a-lq-z] |
[a-z-[^def]] |
d,e, orf |
|
|
Predefined Character Classes | |
. |
Any character (may or may not match line terminators) |
\d |
A digit:[0-9] |
\D |
A non-digit:[^0-9] |
\s |
Awhitespacecharacter:[ \t\n\x0B\f\r] |
\S |
A non-whitespacecharacter:[^\s] |
\w |
A word character:[a-zA-Z_0-9] |
\W |
A non-word character:[^\w] |
보다자세한설명과예제는J2SE 1.4 API문서의java.util.regex.Pattern을참조하도록하자.
클래스와메소드
Pattern클래스
Pattern객체는Perl문법과비슷한형태로정의된정규표현식을나타낸다.
문자열로정의한정규표현식은사용되기전에반드시Pattern클래스의인스턴스로컴파일되어야한다.컴파일된패턴은Matcher객체를만드는데사용되며, Matcher객체는임의의입력문자열이패턴에부합되는지여부를판가름하는기능을담당한다.또한Pattern객체들은비상태유지객체들이기때문에여러개의Matcher객체들이공유할수있다.
다음은Pattern클래스의주요메소드들에대한설명이다.
static Pattern compile(Stringregex):주어진정규표현식으로부터패턴을만들어낸다(이를‘컴파일한다’고표현한다).
static Matchermatcher(CharSequenceinput):입력캐릭터시퀀스에서패턴을찾는Matcher객체를만든다.
String[] pattern():컴파일된정규표현식을String형태로반환한다.
String[] split(CharSequenceinput):주어진입력캐릭터시퀀스를패턴에따라분리한다.
/*
* split메소드를이용해입력시퀀스를콤마(‘,’)와공백문자를기준으로
*나눈다.
*/
import java.util.regex.*;
public class Splitter {
public static void main(String[] args) throws Exception {
//한개이상의연속된‘,’와공백문자를의미하는패턴을만든다.
Pattern p =Pattern.compile("[,{space}]+");
//패턴에따라입력문자열을쪼갠다.
String[] result =
p.split("one,two, three four , five");
for (inti=0;i<result.length;i++)
System.out.println(result[i]);
}
}
Matcher클래스
Matcher객체는특정한문자열이주어진패턴과일치하는가를알아보는데이용된다. Matcher클래스의입력값으로는CharSequence라는새로운인터페이스가사용되는데이를통해다양한형태의입력데이터로부터문자단위의매칭기능을지원받을수있다.기본적으로제공되는CharSequence객체들은CharBuffer, String,StringBuffer클래스가있다.
Matcher객체는Pattern객체의matcher메소드를통해얻어진다. Matcher객체가일단만들어지면주로세가지목적으로사용된다.
l 주어진문자열전체가특정패턴과일치하는가를판단(matches).
l 주어진문자열이특정패턴으로시작하는가를판단(lookingAt).
l 주어진문자열에서특정패턴을찾아낸다(find).
이들메소드는성공시true를실패시false를반환한다.
또한특정문자열을찾아새로운문자열로교체하는기능도제공된다.
appendRepalcement(StringBuffersb, String replacement)메소드는일치하는패턴이나타날때까지의모든문자들을버퍼(sb)로옮기고찾아진문자열대신교체문자열(replacement)로채워넣는다.또한appendTail(StringBuffersb)메소드는캐릭터시퀀스의현재위치이후의문자들을버퍼(sb)에복사해넣는다.다음절에나오는예제코드를참고하도록하자.
CharSequence인터페이스
CharSequence인터페이스는다양한형태의캐릭터시퀀스에대해일관적인접근방법을제공하기위해새로생겨났다.기본적으로String,StringBuffer,CharBuffer클래스가이를구현하고있으므로적절한것을골라사용하면되며,인터페이스가간단하므로필요하면직접이를구현해새로하나만들어도된다.
ExampleRegexScenarios
아래코드는J2SE 1.4도큐먼트의예제를완성한것이다.
/*
*이코드는"One dog, two dogs in the yard."라는문자열을
*표준출력을통해출력한다.
*/
import java.util.regex.*;
public class Replacement {
public static void main(String[] args)
throws Exception {
// ‘cat’이라는패턴생성
Pattern p =Pattern.compile("cat");
//입력문자열과함께매쳐클래스생성
Matcher m =p.matcher("one cat," +
" two cats in the yard");
StringBuffersb= newStringBuffer();
booleanresult =m.find();
//패턴과일치하는문자열을‘dog’으로교체해가며
//새로운문자열을만든다.
while(result) {
m.appendReplacement(sb, "dog");
result =m.find();
}
//나머지부분을새로운문자열끝에덫붙인다.
m.appendTail(sb);
System.out.println(sb.toString());
}
}
메일주소포맷확인
다음코드는주어진입력시퀀스가메일주소포맷인가를판단한다.이코드는가능한모든형태의메일주소를확인하는것은아니니필요하면코드를더추가해사용하자.
/*
*메일주소에서잘못된문자검사
*/
public classEmailValidation{
public static void main(String[] args)
throws Exception {
String input = "@sun.com";
//메일주소가‘.’이나‘@’와같은잘못된문자로시작하는지확인
Pattern p =Pattern.compile("^\\.|^\\@");
Matcher m =p.matcher(input);
if (m.find())
System.err.println("Email addresses don't start" +
" with dots or @ signs.");
//’www.’으로시작하는주소를찾는다.
p =Pattern.compile("^www\\.");
m =p.matcher(input);
if (m.find()) {
System.out.println("Email addresses don't start" +
" with \"www.\", only web pages do.");
}
p =Pattern.compile("[^A-Za-z0-9\\.\\@_\\-~#]+");
m =p.matcher(input);
StringBuffersb= newStringBuffer();
booleanresult =m.find();
booleandeletedIllegalChars= false;
while(result) {
deletedIllegalChars= true;
m.appendReplacement(sb, "");
result =m.find();
}
m.appendTail(sb);
input =sb.toString();
if (deletedIllegalChars) {
System.out.println("It contained incorrect characters" +
" , such as spaces or commas.");
}
}
}
파일에서제어문자제거
/*
*지정된파일에서제어문제를찾아제거한다.
*/
import java.util.regex.*;
importjava.io.*;
public class Control {
public static void main(String[] args)
throws Exception {
//파일객체생성
File fin = new File("fileName1");
Filefout= new File("fileName2");
//입출력스트림생성
FileInputStreamfis=
newFileInputStream(fin);
FileOutputStreamfos=
newFileOutputStream(fout);
BufferedReaderin = newBufferedReader(
newInputStreamReader(fis));
BufferedWriterout = newBufferedWriter(
newOutputStreamWriter(fos));
//제어문자를의미하는패턴생성
Pattern p =Pattern.compile("{cntrl}");
Matcher m =p.matcher("");
StringaLine= null;
while((aLine=in.readLine()) != null) {
m.reset(aLine);
//제어문자들을빈문자열로대체
String result =m.replaceAll("");
out.write(result);
out.newLine();
}
in.close();
out.close();
}
}
파일검색
/*
* .java파일에서주석을찾아출력한다.
*/
import java.util.regex.*;
importjava.io.*;
importjava.nio.*;
importjava.nio.charset.*;
importjava.nio.channels.*;
public classCharBufferExample{
public static void main(String[] args) throws Exception {
//주석을나타내는패턴생성
Pattern p =
Pattern.compile("//.*$",Pattern.MULTILINE);
//소스파일
File f = new File("Replacement.java");
FileInputStreamfis= newFileInputStream(f);
FileChannelfc=fis.getChannel();
//소스파일로부터CharBuffer생성
ByteBufferbb =
fc.map(FileChannel.MAP_RO, 0, (int)fc.size());
Charsetcs=Charset.forName("8859_1");
CharsetDecodercd=cs.newDecoder();
CharBuffercb=cd.decode(bb);
//매칭작업수행
Matcher m =p.matcher(cb);
while (m.find())
System.out.println("Found comment: "+m.group());
}
}
'JAVA > Regular Expression' 카테고리의 다른 글
replaceAll 정규식 팁! (0) | 2013.03.22 |
---|---|
정규식과 보안 (0) | 2013.03.04 |