ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Javascript] 정규 표현식 (Regular Expression)
    Front-End(Web)/Javascript 2022. 2. 15. 02:14
    반응형

    🤔 서론

    Javascript 언어를 사용하거나, 관련 프레임워크로 개발하다 보면 정규식이라는 개념을 종종 접할 수 있다.

    아마도, 다양한 조건을 검색 혹은 대체하기 위한 목적으로 많이 사용해보았을 것이다.

    (이메일, 패스워드 조건 or match(), replace() 메서드 등)

     

    지금까지는, 템플릿화된 정규식을 가져다 쓴게 대부분이고, 그렇기에 문법을 명확히 이해하지 못하고 관습적으로 사용하고 있었다.

    이를 주도적으로 이해하고 직접 작성하기 위해선 제대로 공부해야겠다는 생각을 했고, 이번 포스팅을 그 기회로 삼을 예정이다!


    📒 정규 표현식 (Regular Expression) 이란?

    정규 표현식(이하 정규식) 은 '문자열에 나타나는 특정 문자조합과 대응시키기 위해 사용되는 패턴'으로 MDN 공식문서는 서술하고 있다.

    즉, 정식 프로그래밍 언어이기 보다는, 문자열을 검색하거나 대체하기 위한 형식 언어(formal language) 이다.

     

    Javascript는 직접 빌드된 정규식(라이브러리)을 지원하는 언어 중 하나로, 이 포스팅 역시 Javascript 기준으로 정리하도록 하겠다.

    * Javascript 뿐만 아니라 C, JAVA, 파이썬, 닷넷 등 대부분 언어에서 표준 라이브러리로 제공한다.

     

     

     

    📒 정규식 문법

     

    - 정규식 생성

    정규식을 생성하는 방법은 2가지로 생성자 함수 방식, 리터럴(Literal) 방식이 있다.

     

    1) 생성자 함수 방식

     

    RegExp([패턴], [플래그]) 함수 문법으로 정규식을 생성할 수 있다. 이는, 정규식이 실행되는 시점에 컴파일된다.

    그렇기에, 다른 출처로부터 패턴을 가져오거나 혹은 패턴이 동적으로 변경되어야 하는 경우에 유용하다.

    let pattern = "^abc"
    
    const regexp1 = new RegExp("^abc");
    const regexp2 = new RegExp(pattern, "gi");

     

    2) 리터럴(Literal) 방식

     

    /[패턴]/[플래그] 로 작성하는 보편적인 방법이다. 이는 스크립트 호출 시점에 컴파일되며, 고정적인 정규식을 사용할 때 유용하다.

    const regexp1 = /^abc/;
    const regexp2 = /^abc/gi;

     

     

    - 정규식 매개변수

    정규식은 아래 그림과 같이 슬래쉬(/) 로 선언하며, 사이에는 패턴을, 끝에는 플래그(Optional)를 작성해준다.

    * 출처 : https://poiemaweb.com/js-regexp

    • 패턴(pattern) : 필수사항. 실행하고자 하는 정규식의 표현이 들어가는 부분이다.
    • 플래그(flag) : 선택사항. 정규식 실행에 필요한 옵션

     

     

    1) 패턴 문법

     

    먼저, 패턴을 작성하기 위한 다양한 문법을 정리해보았다.

    찾고자하는 문자열만 작성해도 되지만, 범위나 조건 등 다양한 문법도 정규식이 지원하고 있다.

     

    [매칭 패턴 (문자, 숫자, 기호 등)]

    문자 의미 상세
    a-z
    A-Z
    영어 영어 알파벳. -으로 범위를 지정한다.
    ㄱ-ㅎ
    가-힣
    한글 한글 문자. -으로 범위를 지정한다.
    0-9 숫자 숫자. -으로 범위를 지정한다.
    . 전체 문자열 개행문자(다음 줄 문자, \n)를 제외한 모든 문자열에 매칭한다.
    ➤ /.n/ 은 "mn"과 매칭된다. "nop"와는 매칭되지 않는다.
    \ 이스케이프
    문자
    1. \ + 일반문자

    이는, 일반문자를 일반문자 외의 의미로 해석된다.
    ➤ /\d/는 d와 매칭되지 않는다. \d는 0~9까지 숫자라는 새로운 의미를 가진다.

    2. \ + 특수문자

    이는 반대로, 특수문자를 문법이 아닌 특수문자 자체로 해석한다.
    ➤ /a\*/는 aaaaa 여러개와 매칭되지 않는다. 기존, 앞문자가 여러개인 *의 문법이 아닌, 문자 자체로 해석된다.
    \b 단어 경계 단어의 경계(시작이나 끝) 을 의미한다.
    \B 단어 경계 아님 단어의 경계(시작과 끝)가 아닌 곳을 의미한다.
    [\b] 백스페이스 백스페이스를 의미한다.
     \cX ctrl 키 ctrl + X 문자에 매칭된다. \ca는 "A"인 셈이다.
    \d 숫자 숫자와 매칭된다. 0-9 와 동일.
    \D 숫자가 아닌 것 숫자가 아닌 문자와 매칭된다. [^0-9] 와 동일.
    \f 폼피드 폼 피드(FF, U+000C) 문자(다음 페이지로 넘기는 문자) 에 매칭된다. 
    \n 줄바꿈 줄 바꿈(LF, U+000A) 문자에 매칭된다.
    \r 캐리지 리턴 캐리지 리턴(CR, U+000D) 문자(새 줄이 시작하는 문자) 에 매칭된다.
    \s 스페이스 스페이스, 탭, 폼 피드, 줄 바꿈 등 하나의 공백 문자와 매칭된다.
    \S 스페이스
    아닌 것
    \s 가 아닌 것에 매칭된다.
    \t 탭(U+0009) 문자에 매칭된다.
    \v 수직 탭 수직 탭(U+0008) 문자에 매칭된다.
    \w 영어, 숫자, 언더바 영문, 숫자, 언더바 문자에 매칭된다. [A-Za-z0-9_] 와 동일
    \W 영어, 숫자, 언더바가 아닌 것 \w 가 아닌 것에 매칭된다.
    \숫자 캡처 역참조 정규식 안 [숫자]번 참조 괄호로 기억된 값을 가져온다. () 참조 괄호 문법은 아래를 참고하자.
    ➤ /(foo) (bar) \1 \2/ 의 경우 \1은 (foo), \2는 (bar) 에 대응된다. 즉, /(foo) (bar) foo bar/ 와 같은 의미이다. 
    \0 Null Null 문자와 매칭
    \x 16진수 16진수에 매칭된다. \xhh 는 2자리(hh), \xhhhh 는 4자리(hhhh) 에 매칭된다.

     

    [검색 패턴]

    문자 의미 상세
    | OR 문자1|문자2 는 문자1 혹은 문자2에 대응한다.
    ➤ /a|b/ 는 "a" 와도 "b" 와도 매칭되는 것이다.
    [reg] 문자셋 문자셋(Character Set)을 의미한다. 내부의 모든 정규식을 OR로 처리하는 것이다.
    ➤ /abc/ 는 "abc"에 매칭되나, /[abc]/ 혹은 /[a-c]/ 는 "a", "b", "c" 중 하나라도 포함되면 매칭된다.
    [^reg] 문자셋 제외 대괄호 안의 문자셋을 제외하는 것이다.
    ➤ [^123] 은 "1", "2", "3" 중 어느 것이라도 들어있으면 매칭되지 않는다.
    ^reg 시작 문자열 뒤의 문자열로 시작하는지 여부를 확인한다.
    ➤ /^a/ 는 "abc"와는 매칭된다. "bca"와는 매칭되지 않는다.
    reg$ 끝 문자열 앞 문자열로 끝나는지 여부를 확인한다.
    ➤ /z$/ 는 "xyz"와는 매칭된다. "yza"와는 매칭되지 않는다.

     

    [개수(수량) 반복 패턴]

    문자 의미 상세
    ? 최소 반복
    문자열
    앞 문자열이 0~1번 반복되는지 여부를 확인한다. {0,1}과 동일하다.
    ➤ /e?le?/ 는 "ele", "el" "l" 모두 매칭된다.

    또, *, +, ?, {} 패턴은 가능한 많은 문자열을 매칭하나, 해당 패턴 뒤에 ?를 사용하면 가능한 적은 문자열을 매칭한다.
    ➤ "123"에 대해서, /\d+/ 는 "123"과 매칭되지만, /\d+?/ 는 "1"하고만 매칭을 한다.
    * 반복 문자열
    (0회 이상)
    앞 문자열이 0번 이상 반복되는지 여부를 확인한다. {0,}와 동일하다.
    ➤ /ab*/ 는 "abbb", "ab", "a" 모두 매칭된다. 특히, /c*/ 는 "abd" 처럼 포함되지 않은 문자와도 매칭된다.(0번)
    + 반복 문자열
    (1회 이상)
    앞 문자열이 1번 이상 반복되는지 여부를 확인한다. {1,}와 동일하다.
    ➤ /ab+/ 는 "abbbb", "ab" 모두 매칭된다. 하지만 "a" 와는 매칭되지 않는다.
    *? 반복 문자열
    (0회, lazy)
    앞 문자열이 0번 이상 반복되는지를 확인하되, 가능한 적게 일치하는 값을 찾는다. {0}과 동일하다.
    ➤ "123"에 대해서, /\d+/ 는 "123"과 매칭되지만, /\d+?/ 는 "1"하고만 매칭을 한다.
    +? 반복 문자열
    (1회, lazy)
    앞 문자열이 1번 이상 반복되는지를 확인하되, 가능한 적게 일치하는 값을 찾는다. {1}과 동일하다.
    {n} 횟수 앞 문자가 n번 반복되었을 경우 매칭된다.
    ./a{2}/ 는 "aa", "aaa" 등과는 모두 매칭된다. 하지만, "a"와는 매칭되지 않는다.
    {n,m} 횟수
    (최소, 최대)
    앞 문자가 n번 이상, m번 이하 반복된 경우에만 매칭된다.
    ➤ /a{2,3}/ 은 "aa", "aaa" 등과 매칭되며, "aaaa"의 경우 맨 앞의 "aaa" 에 매칭된다. (?를 붙이면 최소인 "aa")

     

    [그룹 패턴]

    문자 의미 상세
    (x) 포획 괄호 x를 그룹화해서 검색하고 이를 캡쳐(기억)한다. 이를, 포획 괄호(capturing parentheses) 라고 한다.
    ➤ /ko+/ 는 "kooo" 등과 매칭되나, /(ko)+/ 는 "koko" 등과 매칭된다. (ko를 그룹화)
    ➤ 또, /(ko)+/ 는 "koko" 에 대한 매칭결과로, "koko"(그룹화된 ko의 반복), "ko"(캡처된 포획괄호 내 문자열) 2가지를 반환한다. (캡처된 문자열은 \숫자 로 역참조 가능, 상단 참고)
    (?:x) 비포획 괄호 x를 그룹화해서 검색하되 캡쳐하지 않는다. 이를, 비포획 괄호(non-capturing parentheses) 라고 한다.
    ➤ "koko" 에 대해 /(ko)+/ 는 "koko", "ko" 2가지를 반환하나, /(?:ko)+/ 는 "koko"(그룹화) 만 반환한다.
    x(?=y) 앞쪽 일치 y가 뒤따라오는 x에만 매칭된다. 앞쪽 일치(Lookahead) 라고 한다.
    ➤ /foo(?=bar)/ 는 "foobar" 와는 매칭된다. "foocar" 와 같이 뒷 패턴이 일치하지 않으면 매칭되지 않는다.
    x(?!y) 부정 앞쪽 일치 y가 뒤따라오지 않는 x에만 매칭된다. 부정 앞쪽 일치(Negative Lookahead) 라고 한다.
    ➤ /foo(?!bar)/ 는 "foo", "foocar" 등 모든 "foo"에 대응하나, "foobar"는 "bar"가 뒤따라오므로 매칭되지 않는다.
    (?<=x)y 뒤쪽 일치 x가 앞선 y에 매칭된다. 뒤쪽 일치(Lookbehind) 라고 한다.
    (?<!x)y 부정 뒤쪽 일치 x가 앞서지 않는 y에만 매칭된다. 부정 뒤쪽 일치(Negative Lookbehind) 라고 한다.

     

     

    2) 플래그 옵션

     

    플래그는 패턴처럼 필수사항은 아니다. 정규식을 사용할 때 고급검색 옵션 설정을 위한 방법이다.

    const regex1 = /abc/flags;
    const regex2 = new RegExp(/abc/, flags);
    플래그 의미 상세
    i Ignore Case 대소문자 구별 없이 검색
    g Global 문자열 내 모든 패턴을 검색한다. matchAll() 메서드와 역할이 비슷.
    m Multi Line 문자열의 행이 바뀌어도 검색을 계속한다.
    u Unicode 유니코드 전체를 지원
    y sticky 문자 내 특정 위치에서 검색을 진행하는 sticky 모드 활성화. regex.lastIndex = [인덱스] 로 범위 설정 등.
    s . 고도화 .(모든 문자 매칭) 문법이 개행문자(\n) 도 포함하도록 한다. ES2018 추가됨.

     

     

    - 정규식 메서드

    정규식 혹은 정규식이 활용되는 String 메서드들이 있다.

    이러한 메서드들로 매칭되는 문자열 혹은 매칭여부를 추출하거나, 다른 문자열로 변환한다.

    메서드 상세
    /정규식/.exec("문자열") 문자열에서 정규식에 매칭되는 부분의 정보를 반환한다.
    매칭되는 가장 앞부분을 결과로 반환하며, 매칭된다면 아래와 같은 값들을 배열로 반환한다.
    (없으면 null)
    * [매칭 텍스트, 포획괄호 캡쳐된 값들... , index: 매치 인덱스, input: 입력 문자열, indices: 그룹화 관련] (참고)
    /정규식/.test("문자열") 문자열에서 정규식이 매칭되는지 여부를 Boolean으로 반환한다. 통상, 정규식 검사에 많이 쓰인다.
    "문자열".match(/정규식/) 문자열에서 정규식이 매칭되는 항목의 정보를 반환한다. exec() 메서드와 유사하다.
    모든 매칭값 정보를 반환하는 matchAll() 메서드도 최근 지원되었다.(ES2020)
    "문자열".split(/정규식/) 정규식에 매칭되는 부분들을 기준으로 문자열을 나누어 배열로 반환한다.
    "문자열".replace(/정규식/, "대체문자열") 정규식에 매칭되는 부분을 대체 문자열로 치환한다.
    모든 매칭값을 치환하기 위해 g플래그를 썼지만, replaceAll() 메서드도 최근 지원되었다.(ES2021)

    📒 정규식 사용 예시

    지금까지 정규식을 사용하기 위한 문법들을 알아보았으며, 이를 기반으로 자주 사용되는(앞으로 나도 프로젝트에 적용할) 몇 가지 정규식들의 예제를 정리해보겠다.

     

    1) 체크 정규식

    const regex = /^[0-9]+$/;				// 숫자만
    const regex = /^[a-zA-Z]+$/;				// 영어만
    const regex = /^[가-힣]+$/;				// 한글(음절)만
    const regex = /\[\]\{\}\/\(\)\.\?\<\>!@#$%^&*/g		// 특수기호들

     

    2) 웹사이트 주소

    const regex = /https?:\/\/[\w\-\.]+/g;

     

    3) 전화번호

    const regex = /^\d{2,3}-\d{3,4}-\d{4}$/		// 일반 전화번호
    const regex = /^\d{3}-\d{3,4}-\d{4}$/		// 휴대폰번호

     

    4) 이메일 체크

    const regex =  /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i;

     

    5) 아이디 혹은 비밀번호 체크

    const regexr = /^[A-Za-z0-9]{4,10}$/;
    // 영문(대,소문자) 또는 숫자로 4~10자리

    정규식을 종종 사용해오며, 이미 작성된 것들만 차용해왔기 때문에 적어도 그 의미를 알고 나중엔 직접 만들어도 봐야겠다는 생각에 이번 포스팅을 계획하게 되었다.

     

    특히, 정규식을 작성하면서 테스트해볼 수 있는 좋은 사이트들이 몇 군데 존재한다.

    https://regex101.com/
    https://regexr.com/
    https://regexper.com/

     

     

    📎 출처

    - [정규식 기본] MDN 공식문서 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions

    - [정규식 정리(패턴)] https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EC%A0%95%EA%B7%9C%EC%8B%9D-RegExp-%EB%88%84%EA%B5%AC%EB%82%98-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC

    - [정규식 정리(패턴)] https://beomy.tistory.com/21  

    - [정규식 정리(패턴)] https://heropy.blog/2018/10/28/regexp/  

    - [정규식 사용예시] https://curryyou.tistory.com/234

    반응형
Designed by Tistory.