상세 컨텐츠

본문 제목

[정규식] _포함 안포함 비교

자바

by esoesmio 2023. 3. 24. 08:20

본문

✔ 정규 표현식(Regular Expression)

 

안녕하세요, 이번에 정리할 내용은 Java에서의 정규 표현식(Regular Expression) 입니다.

 

최근 개발을 하면서 정규 표현식을 사용하면 더 간단하게 해결할 수 있는 문제들을 꽤 자주 접했었고,

그때마다 주먹 구구식으로 정확한 이해없이 검색을 통해 해결을 해왔었습니다...

따라서 이번에 정리를 한 번 하려고 합니다 ✏

 

 

위키백과에 나와있는 정규 표현식의 정의는 다음과 같습니다.

정규 표현식(正規表現式, 영어: regular expression, 간단히 regexp[1] 또는 regex, rational expression)[2][3] 또는 정규식(正規式)은 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다. 정규 표현식은 많은 텍스트 편집기 프로그래밍 언어에서 문자열의 검색과 치환을 위해 지원하고 있으며, 특히  Tcl은 언어 자체에 강력한 정규 표현식을 구현하고 있다.

컴퓨터 과학의 정규 언어로부터 유래하였으나 구현체에 따라서 정규 언어보다 더 넓은 언어를 표현할 수 있는 경우도 있으며, 심지어 정규 표현식 자체의 문법도 여러 가지 존재하고 있다. 현재 많은 프로그래밍 언어, 텍스트 처리 프로그램, 고급 텍스트 편집기 등이 정규 표현식 기능을 제공한다. 일부는 , 자바스크립트, 루비, Tcl처럼 문법에 내장되어 있는 반면 닷넷 언어, 자바, 파이썬, POSIX C, C++ (C++11 이후)에서는 표준 라이브러리를 통해 제공한다. 그 밖의 대부분의 언어들은 별도의 라이브러리를 통해 정규 표현식을 제공한다.

정규 표현식은 검색 엔진, 워드 프로세서 문서 편집기의 찾아 바꾸기 대화상자, 그리고 sed, AWK와 같은 문자 처리 유틸리티, 어휘 분석에 사용된다.

ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D

위에서 핵심 문장은 다음과 같습니다.

"특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어"

 

 

정규 표현식은 대부분 문자열과 관련된 문제 해결을 위해 사용합니다.

가장 많이 사용하는 예시가 이메일, 핸드폰 번호 등의 유효성 검사를 위해 사용합니다.

 

정규 표현식에 대해 문법과 예제를 통해 좀 더 자세히 살펴보도록 하겠습니다.


 

 

🎗 정규 표현식 문법

정규 표현식의 기호는 다음과 같습니다.

 

※ 2021.08.09 \w, \W 내용 수정

\w 의 경우 알파벳이나 숫자, 언더바(_) 기호를 찾습니다.

\W 의 경우 알파벳이나 숫자, 언더바(_)를 제외한 문자입니다.

public class Tests {
    public static void main(String[] args) {
        String str = "a_b-c";
        System.out.println(str.replaceAll("\\W", ""));
    }
}

 

 

따라서 언더바도 제외를 해야할 경우, 다음과 같이 작성을 해야 합니다. 😭

String str = "a_b-c";
System.out.println(str.replaceAll("[\\W_]", ""));
// System.out.println(str.replaceAll("[a-zA-Z0-9]", "")); 위와 동일한 결과

 

 

 

 

 

 

정규 표현식의 대부분은 위에 내용이 전부인데요, 위 내용을 이해하더라도 실제로 사용되는 정규식을 살펴보면 

무슨 의미를 뜻하는지 이해하기 힘든 정규식이 몇몇 존재합니다... 🤦‍♂️

따라서 위 정규 표현식에서 더 나아가 실제 예제를 통해 살펴보겠습니다.

 

위 정규 표현식 기호에서 기억해야 할 점은, 백슬러시(\) 가 포함되어 있는 기호들입니다.

정규 표현식에서 백슬러시(\)는 확장 문자로, 다음에 일반 문자가 오면 특수문자로 취급하고, 백슬러시 다음에 특수문자가 오면 그 문자 자체를 의미합니다.

 

예를 들어, 알파벳이나 숫자를 나타내는 \w 같은 경우 Java에서 \ 자체는 특수문자로 취급하기 때문에, 알파벳이나 숫자를 판별하는 정규식 기호는 다음과 같이 작성을 해야합니다.

\\w // 알파벳이나 숫자

위 설명만 보고는 정확히 무엇을 의미하는지 이해하기가 힘들 수 있으므로, 아래에서 살펴볼 예제를 통해 이해하시면 될 것 같습니다 !!

 

 

정규 표현식 관련해서 너무나 다양한 기호들이 존재하기 때문에, 전부 다 외우는 것은 불가능하고,

어떠한 상황에 어떠한 기호가 사용되는지 이해하는 것이 중요한 것 같습니다.

 

개인적으로 주로 사용하는 기호들은 다음과 같습니다.

[]  ()  \w  *  +  {}  ^  $  ...

 

 

자주 사용하는 패턴의 정규 표현식을 나타내보면 다음과 같습니다.

정규 표현식 의미
^[0-9]*$ == \\d 숫자
^[a-zA-Z]*$ 알파벳
^[가-힣]*$ 한글
^[a-zA-Z0-9] 알파벳이나 숫자
^[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-z]+$ 이메일(Email)
\w+@\w+\.\w+(\\.\\w+)? 이메일(Email)
^01(?:0|1|[6-9])-(?:\\d{3}|\\d{4})-\\d{4}$ 휴대폰 번호

위와 같이 일반적으로 자주 사용되는 정규 표현식이 존재하는데요, 처음 봤을땐 각 표현식이 무슨 의미를 나타내는지 파악하기 힘들 수 있습니다.

 

예제를 통해 정규 표현식을 익힐 것을 추천드립니다 !!


 

 

 

🎗 정규 표현식 예제

예제에서 살펴볼 클래스 및 메소드는 다음과 같습니다.

클래스 및 메소드에 대한 자세한 내용은 공식 문서를 참고해주세요 !

docs.oracle.com/javase/8/docs/api/

 

Java Platform SE 8

 

docs.oracle.com

 

 

 

Pattern 클래스

  • 정규 표현식에 대한 문자열글 검증하는 기능
  • 공개된 생성자를 제공하지 않음
  • 패턴을 생성하려면 Pattern 객체를 반환하는 정적 compile 메소드를 호출해야 함
  • matches() 메소드를 활용하여 검증
  • regex: 정규 표현식
  • input: 검증할 문자열
    public static boolean matches(String regex, CharSequence input) {
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(input);
        return m.matches();
    }

 

 

 

Matcher 클래스

  • 패턴을 해석하고 입력 문자열에 대해 일치 작업을 수행하는 엔진
  • Pattern 클래스와 동일하게 어떠한 공개된 생성자도 정의하고 있지 않음
  • Pattern 객체의 matcher() 메소드를 호출해서 얻음
  • matches() 메소드를 활용하여 검증
  • regex: 정규 표현식
  • input: 검증할 문자열
    /**
     * Creates a matcher that will match the given input against this pattern.
     *
     * @param  input
     *         The character sequence to be matched
     *
     * @return  A new matcher for this pattern
     */
    public Matcher matcher(CharSequence input) {
        if (!compiled) {
            synchronized(this) {
                if (!compiled)
                    compile();
            }
        }
        Matcher m = new Matcher(this, input);
        return m;
    }

 

 

 

String.replaceAll()

  • Java의 문자열에서 정규식을 사용하는 메소드 중 하나입니다.
  • 문자열 내에 있는 정규식(regex)와 매칭되는 모든 문자열을 replacement 문자로 치환합니다.
    public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }

 

 

저는 String 클래스의 replaceAll() 메소드를 통해 정규 표현식이 어떻게 사용되는지 살펴보겠습니다 !!

 

Pattern 클래스 및 Matcher 클래스에 대한 사용법은 아래 블로그를 참고해 주세요 😊

blog.naver.com/zzang9ha/222013925468

 

[Java/자바] - 정규 표현식(Regular Expression)

안녕하세요~ 이번 시간에 정리할 내용은 "정규 표현식" 입니다.평소에 코딩을 하면서 정규표현식...

blog.naver.com

 

coding-factory.tistory.com/529

 

[Java] 자바 정규 표현식 (Pattern, Matcher) 사용법 & 예제

정규표현식(Regular Expression)이란 컴퓨터 과학의 정규언어로부터 유래한 것으로 특정한 규칙을 가진 문자열의 집합을 표현하기 위해 쓰이는 형식언어 입니다. 개발을 하다보면 전화번호, 주민등

coding-factory.tistory.com


 

 

🎗String.replaceAll(String regex, String replacement)

예제는 2021 카카오 블라인드 채용 코딩 테스트의 문제인 신규 아이디 추천 입니다.

 

위와 같이 아이디의 유효성을 검사하는 여러 단계가 존재하는데요,

각 단계를 정규 표현식을 통해 처리를 하면 간단하게 해결할 수 있습니다.

 

위 문제에서 정규 표현식을 통해 해결할 수 있는 단계는 2단계, 3단계, 4단계, 6단계 정도 인 것 같습니다.

하나씩 살펴봅시다😎

 

 

 

 

🎶 2단계 new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.

 

위에서 핵심 키워드는 알파벳 소문자, 숫자, 빼기, 밑줄, 마침표 입니다.

정규 표현식은 알파벳 소문자(a-z), 숫자(0-9 혹은 \d), 빼기&밑줄&마침표(-_.) 입니다.

 

따라서 2단계를 정규 표현식을 통해 모든 문자를 제거하는 코드는 다음과 같습니다.

// String s
s = s.replaceAll("[^a-z\\d\\-_.]*", "");
  • ^의 경우 문자열의 시작을 의미하지만, [] 내에 존재하면 not 을 의미합니다.
  • 위에서 설명드렸듯이, 백슬러시(\)를 두 번 써주어야 정상적인 검사가 가능합니다.

 

위 정규 표현식을 더 간단하게 줄이면 다음과 같습니다.

s = s.replaceAll("[^\\w\\-_.]*", "");
  • 2단계의 유효성 검사에는 일치하지 않지만, 문제의 1단계에서 이미 모든 문자를 소문자로 치환했기 때문에 위와 같이 \w(알파벳이나 숫자)를 작성해주어도 결과는 동일합니다.
  • 위 정규 표현식은 문자열에 대문자가 존재하면, 대문자는 제거해주지 않습니다.

 

 

 

 

🎶 3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.

 

위에서 핵심 키워드는 2번 이상 연속된 부분입니다.

위의 유효성 검사는 정규 표현식을 사용하지 않고 가능하겠지만, 코드가 복잡하게 될 거라고 생각합니다...🤔

 

따라서 위 문제를 해결하기 위해 횟수 또는 범위를 나타내는 {} 기호를 사용합니다.

// "[.]{2.}"
s = s.replaceAll("\\.{2,}", ".");

 

  • 주석 처리된 정규 표현식과 replaceAll에 작성된 정규 표현식을 동일한 의미입니다.
  • \\. (마침표)
  • {2,} 2회 이상

 

 

 

 

🎶 4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.

 

위에서 마침표(.)가 처음이나 끝에 위치한다면 제거를 해야하는데요, 만약 정규 표현식을 사용하지 않는다면 ..

첫 문자와 마지막 문자가 마침표(.) 인지 여부를 판단해서 제거해야 합니다.

 

하지만, 정규 표현식을 통해 간단히 해결이 가능합니다.

s = s.replaceAll("^[.]|[.]$", "");
  • ^  문자의 시작을 의미합니다.
  • [.] 는 . 을 의미하고, 즉 ^[.]  문자열이 마침표(.)로 시작하는 것을 의미합니다.
  • | 는 패턴 안에서 or 연산(처음이나 끝에 위치하는 경우)을 의미합니다.
  • [.]$ 는 문자열의 끝이 마침표(.)로 끝나는 것을 의미합니다.

 

2022.02.07 추가

  • 위 정규 표현식은 대괄호를 생략하고다음과 같이 나타낼 수 있습니다.
s = s.replaceAll("^.|.$", "");

 

 

 

🎶 6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다. 만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.

 

위에서 마침표(.)가 끝에 위치하는 경우는 4단계에서 작성을 해보았습니다.

따라서 6단계의 전체 검사를 나타내는 코드는 다음과 같습니다.

        private KakaoId notGraterThan16() {
            if (s.length() >= 16) {
                s = s.substring(0, 15);
            }
            s = s.replaceAll("[.]$", "");
            return this;
        }

 

 

이상으로 자바 정규 표현식에 대해 살펴보았습니다!

정규 표현식은 정말 자주 사용하는 것은 아니지만, 알아두면 꼭 사용해야 할 때가 있는 것 같습니다.

따라서 정규 표현식에 대해 어느정도 이해하고, 써먹을 수 있을 정도로는 공부를 하는 것이 좋을 것 같습니다. 

'자바' 카테고리의 다른 글

스트림 외울거  (0) 2023.03.30
[객체배열] 오름차순  (0) 2023.03.24
[인터페이스,추상클래스] 비교글  (0) 2023.03.24
[재귀함수]  (1) 2023.03.24
[문자열붙이는방법]  (0) 2023.03.24

관련글 더보기

댓글 영역