[modern JS Deep Dive] - 31장 . RegExp

유선향·2025년 1월 18일
0

<modern_JS_Deep_Dive>

목록 보기
28/44

정규 표현식 이란?

  • 일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어
  • 정규 표현식은 문자열을 대상으로 패턴 매칭 기능 (특정 패턴과 일치하는 문자열을 검색 or 추출 또는 치환할 수 있는 기능)을 제공한다.

정규 표현식의 생성

  • 정규 표현식 리터럴 방식과 RegExp 생성자 함수 두가지 방법으로 정규 표현식 객체를 생성할 수 있다.

  • 패턴과 플래그로 구성된다.

    플래그

    • g : 모든 문자열을 검색한다.

    • i : 대소문자를 구별하지 않고 검색한다.

    • m : 문자열의 행이 바뀌더라도 패턴 검색을 계속한다.

    • u: 패턴을 유니코드 기준으로 해석

      • 기본적으로 JS의 정규식은 UTF-16 단위(2바이트)로 동작 → 이모지 같은 “보충 평면 문자(서로게이트 페어)”는 한 글자지만 두 글자로 인식됨.
    • y: sticky 모드 (lastIndex에서만 매치, 토큰화/파싱 용도로 사용)
      - 정규식의 실행으로(exec, test)매칭이 성공하면, 매치가 끝난 지점의 인덱스가 lastIndex에 기록됨.

      패턴

    • 문자열의 일정한 규칙을 표현하기 위해 사용된다.

    • . : 점은 임의의 문자 한개를 의미한다.

      • e.g.) /…/g ; ⇒ 문자의 내용과 상관없이 3자리 문자열과 매치한다.
    • {m, n} : 최소 m 번, 최대 n 번 반복되는 문자열을 의미한다 , 콤마뒤에 공백 필수

      • n 이 없이 m 만 존재할 경우, m 번 반복되는 문자열
      • n이 없이 m, 만 존재할경우, 최소m 번 이상 반복되는 문자열
    • | : /a|b/ ⇒ a 혹은 b 라는 의미

      • /a+|b+/g a로 시작하는 단어 혹은 b로 시작하는 단어
      • /a|b/ === /[ab]/ 와 똑같이 동작한다
    • d : 숫자를 의미한다.
      - /[\d]+/g ⇒ 0~9가 한번 이상 반복되는 문자열을 전역 검색한다

      예시1)

      const target = 'is this all there is?'
      
      const regexp = /is/i;
      //패턴 : is
      //플래그 : i -> 대소문자 구별하지 않고 검색 
      
      regexp.test(target) //true

자주 사용하는 정규 표현식 리터럴


// 숫자만
const onlyNumbers = /^\d+$/;

// 알파벳만 (대소문자)
const onlyAlphabets = /^[A-Za-z]+$/;

// 한글만
const onlyKorean = /^[가-힣]+$/;

// 이메일 형식
const email = /^[0-9a-zA-Z]([._-]?[0-9a-zA-Z])*@[0-9a-zA-Z]+\.[a-zA-Z]{2,3}$/;

// URL 형식
const url = /^(https?:\/\/)?([\w.-]+)\.([a-z]{2,})([\/\w.-]*)*\/?$/;

// 휴대폰 번호 (010-1234-5678, 01012345678)
const phone = /^01[016789]-?\d{3,4}-?\d{4}$/;

// 주민등록번호 (######-#######)
const koreanID = /^\d{6}-[1-4]\d{6}$/;

// 비밀번호 (영문+숫자+특수문자, 8~20자)
const password = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,20}$/;

// 공백 포함 여부 확인
const hasSpace = /\s/;

// HTML 태그 찾기
const htmlTag = /<\/?[\w\s="/.':;#-\/]+>/gi;

// 특수문자 포함 여부
const hasSpecialChar = /[~!@#$%^&*()_+|<>?:{}]/;

// 앞뒤 공백 제거 (replace용)
const trimSpace = /^\s+|\s+$/g;

// 우편번호 (5자리)
const postalCode = /^\d{5}$/;

// 소수 (정수 또는 소수점 숫자)
const decimal = /^\d+(\.\d+)?$/;

// IPv4 주소
const ipv4 = /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/;

// 날짜 (YYYY-MM-DD)
const date = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;

// 시간 (HH:MM 24시간)
const time = /^([01]\d|2[0-3]):([0-5]\d)$/;

정규 표현식 메서드

const regex = /ab+c/g; 
const str = "ab abc abbc abbbc";

// 1. test() → 문자열이 패턴에 매칭되는지 여부 (true/false)
console.log(/abc/.test("abcdef")); // true
console.log(/abc/.test("defghi")); // false

// 2. exec() → 첫 번째 매칭 결과를 배열로 반환 (없으면 null)
// g 플래그 있으면 lastIndex 기준으로 연속 검색
let re = /ab+/g;
console.log(re.exec("abbc abbbc")); // ['abb', index: 0, input: 'abbc abbbc']
console.log(re.exec("abbc abbbc")); // ['abbb', index: 5, input: 'abbc abbbc']

// 3. match() → 문자열 메서드, 정규식 매칭 결과 반환
console.log("abbc abbbc".match(/ab+/));   // 첫 매치만 → ['abb']
console.log("abbc abbbc".match(/ab+/g));  // 모든 매치 → ['abb', 'abbb']

// 4. matchAll() → g 플래그와 함께 모든 매치를 이터러블로 반환
for (const m of "abbc abbbc".matchAll(/ab+/g)) {
  console.log(m); // ['abb'] , ['abbb']
}

// 5. search() → 문자열 메서드, 첫 매치의 시작 인덱스 반환 (없으면 -1)
console.log("hello abc world".search(/abc/)); // 6
console.log("hello world".search(/abc/));     // -1

// 6. replace() → 매칭된 부분을 다른 문자열로 교체
console.log("abc123".replace(/\d+/, "###")); // abc###
console.log("abc123".replace(/\d/g, "*"));   // abc*** (g 플래그 → 모든 숫자)

// 7. replaceAll() → 문자열 메서드, 모든 매칭 교체 (ES2021+)
console.log("abc123123".replaceAll(/\d/g, "*")); // abc******

// 8. split() → 정규식을 기준으로 문자열 분리
console.log("apple,banana;orange".split(/[,;]/)); // ['apple', 'banana', 'orange']

0개의 댓글