[ DevKnow ] RegEx

codesver·2023년 7월 24일
0

DevKnow

목록 보기
1/1
post-thumbnail

📌 Overview

코딩테스트를 보았는데 주어진 문자열 배열에서 몇개의 문자열이 조건을 만족하는지 물어보는 문제가 있었다. (코딩테스트 문제에 대한 자세한 언급 불가) 처음에는 반복문을 돌리면서 각각의 조건을 확인하고자 하였다. 그러나 그러면 코드가 너무 많아질 것 같아서 정규표현식을 써서 풀었다. 주어진 테스트케이스들은 모두 통과하였지만 나중에 코드를 다시 확인해보니 틀린 부분이 있었다. 그래서 이참에 정규표현식에 대해서 확실하게 정리하고 가려고 한다.

📌 그래서 정규표현식이 뭔데?

정규표현식을 구글에 검색하면 이렇게 나온다. "정규표현식 또는 정규식은 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다". 정규표현식을 어느정도 알고 있는 개발자 입장에서는 굉장히 이해하기 쉬운 설명이다. 하지만 처음 듣는 사람은 이해하기 어려울 수 있다. 그렇기 때문에 예시를 들어 설명하고자 한다.

위의 그림처럼 정규표현식의 예시로 가장 많이 나오는 것이 이메일 주소이다. 그중에서 [A-Za-z]{2, 3}을 봐보자. 대괄호 [ ]는 대괄호 안에 있는 문자가 나온다는 것이다. A-Z와 a-z는 알파벳 전체를 의미한다. 즉, [A-Za-z]는 알파벳 문자 하나를 의미한다. 그런데 뒤에 중괄호 { }는 횟수를 의미한다. {n}은 앞의 문자가 n번 반복됨을, {n,}은 n번 이상을 {n, m}은 n번 이상 m번 이상 반복됨을 의미한다. 다시 말해 [A-Za-z]{2, 3}은 알파벳이 2번 또는 3번 나와야 함을 의미한다. "aBc"나 "odJ"등은 이런 정규표현식 집합에 포함된다. 반면에 "1ab"이나 "알파벳"등은 포함되지 않는다.

📌 RegEx

그럼 이제 정규 표현식에서 사용할 수 있는 규칙들을 정리하려고 한다. 정규 표현식에서 사용하는 용어들을 Meta 문자라고 한다.

MetaContentRegexString
^^는 문자열의 시작을 나타낸다."^x""xyz"
$$는 문자열의 종료를 나타낸다."x$""zyx"
..은 어떤 문자 한개를 뜻한다."....""abcd"
++는 앞의 문자가 1개 이상 반복됨을 의미한다."x+""xxxxxxx"
**는 앞의 문자가 0번 이상 반복됨을 의미한다."x*"xxxxxx"
??는 존재 여부를 나타내며 앞의 문자가 있을 수도 없을 수도 있다."x?""x"
||는 or을 나타내는 언어이다."a|b""a"
[ ]대괄호는 다중 or문이다. 대괄호 안에 있는 문자열 중 하나를 나타낸다."[abc]""a"
[^]대괄호 안에서 맨 앞에 ^를 붙이면 not 표시가되어 대괄호 내의 문자가 아니라는 뜻이다."[^abc]""d"
[-]대괄호 안에서 -는 범위를 뜻한다. A-Z는 대문자, a-z는 소문자, 0-9는 숫자 등이 있다."[0-9]""7"
{n}중괄호는 반복을 표현하며 앞의 문자가 n번 반복됨을 의미한다."[0-9]{2}""25"
{n,},는 이상을 뜻하며 앞의 문자가 n번 이상 반복됨을 의미한다."[0-9]{3,}""250"
{n,m}앞의 문자가 n번 이상 m번 이하 반복됨을 의미한다."[0-9]{3, 5}""1234"
()소괄호는 그룹의 의미한다."(abc)+""abcabc"

더 자세한 규칙들은 다음을 참고하면 된다.
More Details

📌 Example

이해를 돕기 위해 예시를 들고자 한다.

사람들의 정보가 담긴 이차원 문자열 배열 infos가 주어진다(String[][] infos). infos[3]은 index 3번인 사람의 정보가 담겨 있다.
- 각각의 사람은 닉네임, 번호, 이메일 정보를 가지고 있다.
- 닉네임은 영어 3개 이상의 대소문자, 숫자로 구성되며 마지막에는 특수 기호 하나를 반드시 가져야 한다.
- 특수 기호는 !, #, $, % 중에 하나이다.
- 번호는 010으로 시작되고 8개의 숫자가 뒤를 따른다. -는 있을 수도 있고 없을 수도 있다.
- 이메일은 NAME@DOMAIN.TOP_DOMAIN으로 구성된다.
- NAME은 닉네임과 조건이 같으나 특수기호는 없어야 한다.
- DOMAIN은 google이다.
- TOP_DOMAIN은 com, net 중에 하나이다.

public long solution(String[][] infos) {
    return Arrays.stream(infos).filter(info ->
            info[0].matches("[A-Za-z]{3,}[!#$%]")
                    && info[1].matches("^(010)-?[0-9]{4}-?[0-9]{4}")
                    && info[2].matches("[A-Za-z]{3,}(@google.)(com|net)")
    ).count();
}
profile
Hello, Devs!

1개의 댓글

comment-user-thumbnail
2023년 7월 24일

공감하며 읽었습니다. 좋은 글 감사드립니다.

답글 달기