정규표현식(REGEX)

소프트웨어 마에스트로 14기 팀 프로젝트에서 나는 백엔드 파트를 담당하여 Spring Boot를 통한 API 서버 개발을 하게 되었다. 프로젝트에서 OCR 기술을 통해 특정 패턴의 문자열을 추출할 일이 생겼고, 이에 대해 이전에 작성한 내용을 팀원들에게 공유해주고자 게시글을 작성하게 되었다.


정규표현식(정규식)이란

  • 특정한 규칙을 가진 문자열의 집합을 표현하는데 사용하는 형식 언어
  • 많은 텍스트 편집기와 프로그래밍 언어에서 문자열의 검색과 치환을 위해 지원하고 있음

패턴이란?

  • 일치하는 텍스트가 준수해야 하는 “패턴”을 표현하기 위해 특정한 표준의 텍스트 신택스(syntax)를 의미하기 위해 사용된다.
  • 정규 표현식의 각 문자(즉, 패턴을 기술하는 문자열 안의 각 문자)는 메타 문자(특별한 의미)로 이해되거나 정규 문자(문자 그대로, 즉 ‘리터럴’의 의미로)로 이해된다.

Java Script 정규표현식 활용

정규표현식 만들기

  1. 정규 표현식 리터럴 : 다음과 같이 슬래시로 패턴을 감싸서 작성

    • 스크립트를 불러올 때 컴파일되므로, 바뀔 일이 없는 패턴의 경우 리터럴을 사용하면 성능이 향상될 수 있다.
    const re = /ab+c/;
    
  2. RegExp 객체의 생성자 호출 : 생성자 함수를 사용하면 정규 표현식이 런타임에 컴파일

    • 바뀔 수 있는 패턴이나, 사용자 입력 등 외부 출처에서 가져오는 패턴의 경우 사용
    const re = new RegExp("ab+c");
    

정규표현식 구조

  1. 데이터의 시작점(^)
  2. (정규표현식 특수문자 구분 참고)
  3. 데이터의 끝점($)

정규표현식 패턴

  1. 단순 패턴 사용하기
    • 문자열을 있는 그대로 탐색할 때 사용
    • ex) /abc/ 패턴
      • “Grab crab” 문자열의 경우 부분 문자열로 “ab c”를 포함하긴 하지만, 정확하게 “abc”를 포함하진 않기 때문
        "Hi, do you know your **abc**'s?"; // 일치 성공
        "The latest airplane designs evolved from sl**abc**raft."; // 일치 성공
        "Gr**ab c**rab"; // 일치 실패
        
  2. 특수 문자 사용하기
    • 직접적인 일치 이상의 탐색이 필요할 땐 특수 문자를 사용
      • 하나 이상의 “b”를 찾거나, 공백 문자를 찾는 등
    • ex) /ab*c/ 패턴
      • 하나의 “a” 이후에 0개 이상의 “b”, 그 뒤의 “c” 일치해야 함
      • “b” 뒤의 “*”는 “이전 항목의 0번 이상 반복”을 의미
        "cbbabbbbcdebc"; // 일치하는 부분 문자열 : "abbbbc"
        

정규표현식 특수문자 구분

  • 문자 클래스
    • . : 1개의 문자와 일치한다.
    • [ ] : “[”와 “]” 사이의 문자 중 하나를 선택한다. “”를 여러개 쓴 것과 같은 의미이다.
  • 어서션
  • 그룹과 범위
    • xy : x 또는 y가 매칭됨
      • /green|red
        "green apple"; // "green"과 매칭
        "red apple"; // "red"와 매칭
        
    • [xyz], [a-c] : 포함된 문자 중 하나와 일치, 하이픈을 사용하여 문자 범위를 지정할 수 있음, 하이픈이 첫번째 혹은 마지막 문자로 나타나면 리터럴 문자로 간주됨
      • [abcd] === [a-d]
        "brisket"; // "b"와 매칭
        "chop"; // "c"와 매칭
        
      • [abcd-] === [-abcd]
        "brisket"; // "b"와 매칭
        "chop"; // "c"와 매칭
        "non-profit"; // a,b,c,d 중 아무것도 매칭되는 것이 없지만, "-"와 매칭이 됨
        
    • [^xyz], [^a-c] : 문자 클래스 안의 문자를 제외한 나머지를 선택한다
    • (x) : 캡처링 그룹, x를 매치, 단순 묶는 용도인듯
  • 수량자
    • ? : 0번 또는 1차례까지의 발생을 의미
      • /colou?r/
        "color"; // 일치
        "colour"; // 일치
        "colouur"; // 불일치
        
      • : 0번 이상의 발생을 의미
        • /ab*c/
          "ac"; // 일치
          "abc"; // 일치
          "abbc"; // 일치
          "abbbc"; // 일치
          
      • : 1번 이상의 발생을 의미
        • /ab+c/
          "ac"; // 불일치
          "abc"; // 일치
          "abbc"; // 일치
          "abbbc"; // 일치
          
    • {n} : 정확히 n번 만큼 일치
    • {min,} : 적어도 min번만큼 일치
    • {min,max} : 적어도 min번만큼 일치시키지만 max번을 초과하여 일치시키지는 않음
  • 유니코드 속성 이스케이프

정규표현식 메서드

  1. exec() : 문자열에서 일치하는 부분을 탐색, 일치 정보를 나타내는 배열(일치가 없는 경우에는 null) 반환
  2. test() : 문자열에 일치하는 부분이 있는지 확인(true or false 반환)
  3. match() : 캡처 그룹을 포함해서 모든 일치를 담은 배열을 반환(일치가 없으면 null) 반환
  4. matchAll() : 캡처 그룹을 포함해서 모든 일치를 담은 반복기를 반환
  5. search() : 문자열에서 일치하는 부분을 탐색, 일치하는 부분의 인덱스(일치가 없는 경우 -1) 반환
  6. replace() : 문자열에서 일치하는 부분을 탐색, 대체 문자열로 변경
  7. replaceAll() : 문자열에서 일치하는 부분을 모두 탐색하고, 모두 대체 문자열로 변경
  8. split() : 정규 표현식 또는 문자열 리터럴을 사용해서 문자열을 부분 문자열의 배열로 나눔

정규표현식 플래그

  1. d : 부분 문자열 일치에 대해 인덱스 생성
  2. g : 전역 탐색
  3. i : 대소문자를 구분하지 않음
  4. m : 여러 줄에 걸쳐 탐색
  5. s : 개행문자가 ‘.’과 일치함
  6. u : “unicode”, 패턴을 유니코드 코드 포인트의 시퀀스로 간주
  7. y : “접착” 탐색, 대상 문자열의 현재 위치에서 탐색을 시작함
  • 플래그 사용
    const re = /pattern/flags;
    
  • 생성자 사용
    const re = new RegExp("pattern", "flags");
    

플래그는 정규식과 완전히 합쳐지므로 나중에 추가하거나 제거할 수 없다.

정규표현식의 실제 활용

  • 검색 엔진
  • 워드 프로세스와 문서 편집기의 찾아 바꾸기 대화상자
  • sed/AWK와 같은 문자 처리 유틸리티
  • 어휘 분석

Reference