인공지능 및 데이터과학/자연어처리

자바(Java) 숫자, 영문, 한글 여부를 체크하는 방법

Steve Jang 2018. 6. 20. 13:19

자바(Java)를 이용해서, 문자의 숫자, 영문, 한글등을 체크하는 방법은 다양하게 많이 존재한다. index 값을 체크하여 문자를 알아내는 고전적인 방식과 정규표현식을 사용해서 체크하는 방법, 그리고 라이브러리를 사용하여 간단하게 체크하는 방법등 여러가지 방식들이 존재한다. 이 포스팅에서는 3가지의 방식을 사용해보고, 각각의 장단점을 정리해보도록 한다.




1. String Index 기법


일단 고전적인 방법으로는 String index값을 이용해서, 한글자 한글자를 읽은 후 index 값이 무엇인지 확인해서 리턴하는 방식이다. 이 방식은 가장 확실하지만, 소스가 지저분해 보일 수 있다. 그리고, 그만큼 강력하다 Low Level의 메소드를 직접 만드는 방법이기 때문에 부가적인 작업(ex: 형태소 분석)들을 처리하기 위해서는 이 방법을 추천한다.


우선 어떤 식으로 진행하는지 확인하기 위해서 index값을 출력하는 코드를 짜본다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class main {
 
    public static void main(String[] args) {
        String sentence = "azAZ019 아이폰6를 샀는데 iphone5보다 이쁘지는 않더라";
        String[] words = sentence.split(" ");
        
        for(String word : words) {
            System.out.println(word + "=>" + getType(word));
        }
    }
    
    
    
    /**
     * 문자의 영문,숫자, 한글 타입을 리턴한다
     * 
     * @param word
     * @return
     */
    public static String getType(String word) {
        for(int i = 0; i < word.length(); i++) {
            int index = word.charAt(i);
            System.out.println(word.substring(i, i+1+ " " + index);
        }        
        
        return "";
    }
}
 
cs


실행을 하면 아래와 같이 결과가 출력된다


a 97

z 122

A 65

Z 90

0 48

1 49

9 57

azAZ019=>

아 50500

이 51060

폰 54256

6 54

를 47484

아이폰6를=>

샀 49344

는 45716

데 45936

샀는데=>

i 105

p 112

h 104

o 111

n 110

e 101

5 53

보 48372

다 45796

iphone5보다=>

이 51060

쁘 49240

지 51648

는 45716

이쁘지는=>

않 50506

더 45908

라 46972

않더라=>


여기서 확인할 수 있는 것은 알파벳은 대문자가 index값이 더 작고, 숫자가 알파벳보다 index가 더 작다는 건데 숫자는 48~57까지이고, 알파벳은 65부터 122까지이다. 위 소스를 이용해서, 단어마다 숫자, 영문, 한글이 포함되어 있는지 체크하는 소스를 짜보도록 하겠다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class main {
 
    public static void main(String[] args) {
        String sentence = "azAZ019 아이폰6를 샀는데 iphone5보다 이쁘지는 않더라";
        String[] words = sentence.split(" ");
        
        for(String word : words) {
            System.out.println(word + "=>" + getType(word));
        }
    }    
    
    
    /**
     * 문자의 영문,숫자, 한글 타입을 리턴한다
     * 
     * @param word
     * @return
     */
    public static String getType(String word) {
        boolean numeric = false;
        boolean alpha = false;
        boolean korean = false;
        StringBuffer sb = new StringBuffer();
        
        for(int i = 0; i < word.length(); i++) {
            int index = word.charAt(i);
            
            if(index >= 48 && index <= 57) {
                numeric = true;
            } else if(index >= 65 && index <= 122) {
                alpha = true;
            } else {
                korean = true;
            }
        }    
        
        if(numeric)
            sb.append("숫자");
        
        if(alpha) {
            if(sb.length() > 0)
                sb.append(",");
            sb.append("영문");
        }
        
        if(korean) {
            if(sb.length() > 0)
                sb.append(",");
            sb.append("한글");
        }
        
        return sb.toString();
    }
}
 
cs


위 소스를 실행하면 아래와 같이 결과를 출력하게 된다


azAZ019=>숫자,영문

아이폰6를=>숫자,한글

샀는데=>한글

iphone5보다=>숫자,영문,한글

이쁘지는=>한글

않더라=>한글


이 방식의 장점은 위에서 설명했던대로 핵심 소스 부분을 직접 코딩하기 때문에 내가 원하는 형태로 리턴을 받을 수가 있는 장점이 있다. 그래서 형태소 분석기등을 만들기에 가장 적합한 방식일 수 있다. 다만 조건이 많아질 경우 패턴이 좀 지저분해질 수 있다는 단점이 있다. 예를 들어 너무 많은 외국어들이 혼재할 경우 처리의 복잡성등이 있을 것이다



2. 정규 표현식을 사용한 방법


정규 표현식을 쓰게 되면, 위 소스의 양을 확 줄일 수 있는 결과를 보여준다. 그래서 숫자, 영문의 순서라든지 문자를 숫자, 영문, 한글 등으로 다시 분리하고 싶다던지 이런 경우를 제외하고는 위 방식보다 정규표현식을 쓰는 것이 훨씬 깔끔하게 표현 될 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.regex.Pattern;
 
public class main {
 
    public static void main(String[] args) {
        String sentence = "azAZ019 아이폰6를 샀는데 iphone5보다 이쁘지는 않더라 東濫漁長進";
        String[] words = sentence.split(" ");
        
        for(String word : words) {
            System.out.println(word + "=>" + getType(word));
        }
    }    
    
    
    /**
     * 문자의 영문,숫자,한글 여부를 리턴한다
     * 
     * @param word
     * @return
     */
    public static boolean getType(String word) {
        return Pattern.matches("^[0-9a-zA-Z가-힣]*$", word);
    }
}
 
cs


해당 메소드는 단어에 숫자,영문,한글이 들어갈 경우, True를 리턴하는데 테스트로 넣은 한자는 False를 리턴하게 된다.


azAZ019=>true

아이폰6를=>true

샀는데=>true

iphone5보다=>true

이쁘지는=>true

않더라=>true

東濫漁長進=>false



3. Apache의 StringUtils을 이용하는 방법


apache의 라이브러리중, common-lang3.jar 라이브러리가 존재하는데 이 라이브러리에는 StringUtils이라는 메소드가 존재한다. StringUtils에는 갖가지 문자열을 체크하는 기능이 있다. 


다운로드 링크

commons-lang3-3.0.1.jar


maven 링크

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-lang3</artifactId>

<version>3.0.1</version>

</dependency>


해당 라이브러리를 classpath에 등록하면, StringUtils이라는 메소드를 사용해서 문자와 숫자를 간단하게 체크할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import org.apache.commons.lang3.StringUtils;
 
public class main {
 
    public static void main(String[] args) {
        String sentence = "2018 azAZ019 아이폰6를 샀는데 iphone5보다 이쁘지는 않더라 東濫漁長進";
        String[] words = sentence.split(" ");
        
        for(String word : words) {
            System.out.println(word + "=>" + getType(word));
        }
    }    
    
    
    /**
     * 문자의 영문,숫자,한글 여부를 리턴한다
     * 
     * @param word
     * @return
     */
    public static String getType(String word) {
        // 숫자로만 구성되어 있을 경우
        if(StringUtils.isNumeric(word)) {
            return "숫자";
        }
        // 숫자가 아닌 문자로 구성되어 있을 경우
        if(StringUtils.isAlpha(word)) {
            return "문자";
        }
        // 숫자와 문자가 섞여 있을 경우
        if(StringUtils.isAlphanumeric(word)) {
            return "숫자+문자";                    
        }
        
        return "";
    }
}
cs


참고로 헷갈릴 수 있는 부분이 메소드의 명칭이 isAlpha라는 것이다. 알파벳만 체크할거라 생각할 수 있지만, 문자는 모두 true로 리턴하게 된다.


2018=>숫자

azAZ019=>숫자+문자

아이폰6를=>숫자+문자

샀는데=>문자

iphone5보다=>숫자+문자

이쁘지는=>문자

않더라=>문자

東濫漁長進=>문자