Post

[모던 자바스크립트 Deep Dive]31장 RegExp

31.1 정규 표현식이란?

1
2
3
4
5
6
7
8
// 사용자로부터 입력받은 휴대폰 전화번호
const tel = '010-1234-567팔';

// 정규 표현식 리터럴로 휴대폰 전화번호 패턴을 정의한다.
const regExp = /^\d{3}-\d{4}-\d{4}$/;

// tel이 휴대폰 전화번호 패턴에 매칭하는지 테스트(확인)한다.
regExp.test(tel); // -> false
  • 일정한 규칙(패턴)을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어(formal language)
  • 패턴과 플래그로 구성
    • 패턴: 문자열의 일정한 규칙
    • 플래그: 정규 표현식의 검색 방식 설정
  • 자바스크립트는 ES3부터 펄(Perl)의 정규 표현식 문법을 도입
  • 반복문과 조건문 없이 패턴을 정의하고 테스트할 수 있지만 가독성이 좋지 않다.

31.2 정규 표현식의 생성

  • 정규 표현식 리터럴을 사용하는 방법

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
      const target = 'Is this all there is?';
        
      // 패턴: is
      // 플래그: i => 대소문자를 구별하지 않고 검색한다.
      const regexp = /is/i;
        
      // test 메서드는 target 문자열에 대해 정규표현식 regexp의 패턴을 검색하여 
      // 매칭 결과를 불리언 값으로 반환한다.
      regexp.test(target); // -> true
    
    • 일반적으로 사용되는 방법
    • /regexp/i
      • /: 시작, 종료 기호
      • regexp: 패턴
      • i: 플래그
  • RegExp 생성자 함수를 사용하는 방법

    1
    2
    3
    4
    5
    
      /**
       * pattern: 정규 표현식의 패던
       * flags: 정규 표현식의 플래그(g, i, m, u, y)
       */
      new RegExp(pattern[, flags])
    
    1
    2
    3
    4
    5
    6
    7
    
      const target = 'Is this all there is?';
        
      const regexp = new RegExp(/is/i); // ES6
      // const regexp = new RegExp(/is/, 'i');
      // const regexp = new RegExp('is', 'i');
        
      regexp.test(target); // -> true
    
    • RegExp 생성자 함수를 사용하면 변수를 사용해 동적으로 RegExp 객체를 생성할 수 있다.

      1
      2
      3
      4
      
        const count = (str, char) => (str.match(new RegExp(char, 'gi')) ?? []).length;
              
        count('Is this all there is?', 'is'); // -> 3
        count('Is this all there is?', 'xx'); // -> 0
      

31.3 RegExp 메서드

31.3.1 RegExp.prototype.exec

1
2
3
4
5
const target = 'Is this all there is?';
const regExp = /is/;

regExp.exec(target); 
// -> ["is", index: 5, input: "Is this all there is?", groups: undefined]
  • 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색하여 매칭 결과를 배열로 반환
  • 매칭 결과가 없는 경우 null 반환

31.3.2 RegExp.prototype.test

1
2
3
4
const target = 'Is this all there is?';
const regExp = /is/;

regExp.test(target); // -> true
  • 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색하여 매칭 결과를 불리언 값으로 반환

31.3.3 String.prototype.match

1
2
3
4
5
const target = 'Is this all there is?';
const regExp = /is/;

target.match(regExp); 
// -> ["is", index: 5, input: "Is this all there is?", groups: undefined]
  • 대상 문자열과 인수로 전달받은 정규 표현식과의 매칭 결과를 배열로 반환
  • 문자열 내의 모든 패턴을 검색하는 g 플래그를 지정하는 경우
    • exec 메서드는 첫 번째 매칭 결과만 반환

      1
      2
      3
      4
      5
      
        const target = 'Is this all there is?';
        const regExp = /is/;
              
        regExp.exec(target); 
        // -> ["is", index: 5, input: "Is this all there is?", groups: undefined]
      
    • match 메서드는 모든 매칭 결과를 배열로 반환

      1
      2
      3
      4
      
        const target = 'Is this all there is?';
        const regExp = /is/g;
              
        target.match(regExp); // -> ["is", "is"]
      

31.4 플래그

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const target = 'Is this all there is?';

// target 문자열에서 is 문자열을 대소문자를 구별하여 한 번만 검색한다.
target.match(/is/);
// -> ["is", index: 5, input: "Is this all there is?", groups: undefined]

// target 문자열에서 is 문자열을 대소문자를 구별하지 않고 한 번만 검색한다.
target.match(/is/i);
// -> ["Is", index: 0, input: "Is this all there is?", groups: undefined]

// target 문자열에서 is 문자열을 대소문자를 구별하여 전역 검색한다.
target.match(/is/g);
// -> ["is", "is"]

// target 문자열에서 is 문자열을 대소문자를 구별하지 않고 전역 검색한다.
target.match(/is/ig);
// -> ["Is", "is", "is"]
  • 플래그는 정규 표현식의 검색 방식
    • i: Ignore case, 대소문자를 구별하지 않고 패턴을 검색
    • g: Global, 대상 문자열에서 패턴과 일치하는 모든 문자열을 전역 검색
    • m: Multi line, 문자열의 행이 바뀌더라도 계속 패턴을 검색
  • 선택적으로 사용할 수 있으며, 순서와 상관없이 하나 이상의 플래그를 동시에 설정 가능
  • 플래그가 설정되지 않은 경우
    • 대소문자를 구별해서 패턴을 검색
    • 패턴 검색 매칭 대상이 1개 이상 존재해도 첫 번째 매칭 대상만 검색하고 종료

31.5 패턴

  • /로 열고 닫으며 문자열의 따옴표는 생략
  • 특별한 의미를 갖는 메타문자 또는 기호로 표현 가능

31.5.1 문자열 검색

  • 패턴에 문자 또는 문자열을 지정하여 이를 검색 가능

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
      const target = 'Is this all there is?';
        
      // 'is' 문자열과 매치하는 패턴. 플래그가 생략되었으므로 대소문자를 구별한다.
      const regExp = /is/;
        
      // target과 정규 표현식이 매치하는지 테스트한다.
      regExp.test(target); // -> true
        
      // target과 정규 표현식의 매칭 결과를 구한다.
      target.match(regExp);
      // -> ["is", index: 5, input: "Is this all there is?", groups: undefined]
    
  • 플래그 i를 사용하여 대소문자를 구별하지 않고 검색 가능

    1
    2
    3
    4
    5
    6
    7
    
      const target = 'Is this all there is?';
        
      // 'is' 문자열과 매치하는 패턴. 플래그 i를 추가하면 대소문자를 구별하지 않는다.
      const regExp = /is/i;
        
      target.match(regExp);
      // -> ["Is", index: 0, input: "Is this all there is?", groups: undefined]
    
  • 플래그 g를 사용하여 패턴과 매치하는 모든 문자열을 전역 검색 가능

    1
    2
    3
    4
    5
    6
    7
    
      const target = 'Is this all there is?';
        
      // 'is' 문자열과 매치하는 패턴.
      // 플래그 g를 추가하면 대상 문자열 내에서 패턴과 일치하는 모든 문자열을 전역 검색한다.
      const regExp = /is/ig;
        
      target.match(regExp); // -> ["Is", "is", "is"]
    

31.5.2 임의의 문자열 검색

1
2
3
4
5
6
const target = 'Is this all there is?';

// 임의의 3자리 문자열을 대소문자를 구별하여 전역 검색한다.
const regExp = /.../g;

target.match(regExp); // -> ["Is ", "thi", "s a", "ll ", "the", "re ", "is?"]
  • .은 임의의 문자 한 개를 의미

31.5.3 반복 검색

  • {m,n}은 앞선 패턴이 최소 m번, 최대 n번 반복되는 문자열을 의미

    1
    2
    3
    4
    5
    6
    
      const target = 'A AA B BB Aa Bb AAA';
        
      // 'A'가 최소 1번, 최대 2번 반복되는 문자열을 전역 검색한다.
      const regExp = /A{1,2}/g;
        
      target.match(regExp); // -> ["A", "AA", "A", "AA", "A"]
    
    • 콤마 뒤에 공백이 있으면 정상 동작하지 않는다.
  • {n}은 앞선 패턴이 n번 반복되는 문자열을 의미

    1
    2
    3
    4
    5
    6
    
      const target = 'A AA B BB Aa Bb AAA';
        
      // 'A'가 2번 반복되는 문자열을 전역 검색한다.
      const regExp = /A{2}/g;
        
      target.match(regExp); // -> ["AA", "AA"]
    
    • {n,n}과 같다.
  • {n,}은 앞선 패턴이 최소 n번 반복되는 문자열을 의미

    1
    2
    3
    4
    5
    6
    
      const target = 'A AA B BB Aa Bb AAA';
        
      // 'A'가 최소 2번 이상 반복되는 문자열을 전역 검색한다.
      const regExp = /A{2,}/g;
        
      target.match(regExp); // -> ["AA", "AAA"]
    
  • +는 앞선 패턴이 최소 한 번 이상 반복되는 문자열을 의미

    1
    2
    3
    4
    5
    6
    
      const target = 'A AA B BB Aa Bb AAA';
        
      // 'A'가 최소 한 번 이상 반복되는 문자열('A, 'AA', 'AAA', ...)을 전역 검색한다.
      const regExp = /A+/g;
        
      target.match(regExp); // -> ["A", "AA", "A", "AAA"]
    
    • {1,}과 같다.
  • ?는 앞선 패턴이 없거나, 최대 한 번 이상 반복되는 문자열을 의미

    1
    2
    3
    4
    5
    6
    7
    
      const target = 'color colour';
        
      // 'colo' 다음 'u'가 최대 한 번(0번 포함) 이상 반복되고 
      // 'r'이 이어지는 문자열 'color', 'colour'를 전역 검색한다.
      const regExp = /colou?r/g;
        
      target.match(regExp); // -> ["color", "colour"]
    
    • {0,1}과 같다.

31.5.4 OR 검색

  • |은 or의 의미가 있다.

    1
    2
    3
    4
    5
    6
    
      const target = 'A AA B BB Aa Bb';
        
      // 'A' 또는 'B'를 전역 검색한다.
      const regExp = /A|B/g;
        
      target.match(regExp); // -> ["A", "A", "A", "B", "B", "B", "A", "B"]
    
    • +를 사용하여 분배되지 않은 단어 레벨로 검색 가능

      1
      2
      3
      4
      5
      6
      7
      
        const target = 'A AA B BB Aa Bb';
              
        // 'A' 또는 'B'가 한 번 이상 반복되는 문자열을 전역 검색한다.
        // 'A', 'AA', 'AAA', ... 또는 'B', 'BB', 'BBB', ...
        const regExp = /A+|B+/g;
              
        target.match(regExp); // -> ["A", "AA", "B", "BB", "A", "B"]
      
  • [] 내의 문자는 or로 동작한다.

    • [] 뒤에 +를 사용하면 앞선 패턴을 한 번 이상 반복
    1
    2
    3
    4
    5
    6
    7
    
      const target = 'A AA B BB Aa Bb';
        
      // 'A' 또는 'B'가 한 번 이상 반복되는 문자열을 전역 검색한다.
      // 'A', 'AA', 'AAA', ... 또는 'B', 'BB', 'BBB', ...
      const regExp = /[AB]+/g;
        
      target.match(regExp); // -> ["A", "AA", "B", "BB", "A", "B"]
    
    • [] 내에 -를 사용하여 범위 지정 가능
    1
    2
    3
    4
    5
    6
    7
    
      const target = 'A AA BB ZZ Aa Bb';
        
      // 'A' ~ 'Z'가 한 번 이상 반복되는 문자열을 전역 검색한다.
      // 'A', 'AA', 'AAA', ... 또는 'B', 'BB', 'BBB', ... ~ 또는 'Z', 'ZZ', 'ZZZ', ...
      const regExp = /[A-Z]+/g;
        
      target.match(regExp); // -> ["A", "AA", "BB", "ZZ", "A", "B"]
    

알파벳을 검색하는 방법

1
2
3
4
5
6
const target = 'AA BB Aa Bb 12';

// 'A' ~ 'Z' 또는 'a' ~ 'z'가 한 번 이상 반복되는 문자열을 전역 검색한다.
const regExp = /[A-Za-z]+/g;

target.match(regExp); // -> ["AA", "BB", "Aa", "Bb"]

숫자를 검색하는 방법

1
2
3
4
5
6
const target = 'AA BB 12,345';

// '0' ~ '9'가 한 번 이상 반복되는 문자열을 전역 검색한다.
const regExp = /[0-9]+/g;

target.match(regExp); // -> ["12", "345"]
  • 매칭 결과가 분리되지 않도록 쉼표를 패턴에 포함할 수 있다.

    1
    2
    3
    4
    5
    6
    
      const target = 'AA BB 12,345';
        
      // '0' ~ '9' 또는 ','가 한 번 이상 반복되는 문자열을 전역 검색한다.
      const regExp = /[0-9,]+/g;
        
      target.match(regExp); // -> ["12,345"]
    

\d

1
2
3
4
5
6
7
8
9
10
11
const target = 'AA BB 12,345';

// '0' ~ '9' 또는 ','가 한 번 이상 반복되는 문자열을 전역 검색한다.
let regExp = /[\d,]+/g;

target.match(regExp); // -> ["12,345"]

// '0' ~ '9'가 아닌 문자(숫자가 아닌 문자) 또는 ','가 한 번 이상 반복되는 문자열을 전역 검색
regExp = /[\D,]+/g;

target.match(regExp); // -> ["AA BB ", ","]
  • 숫자를 의미
  • [0-9]와 같다.
  • \D\d와 반대로 숫자가 아닌 문자를 의미한다.

\w

1
2
3
4
5
6
7
8
9
10
11
const target = 'Aa Bb 12,345 _$%&';

// 알파벳, 숫자, 언더스코어, ','가 한 번 이상 반복되는 문자열을 전역 검색한다.
let regExp = /[\w,]+/g;

target.match(regExp); // -> ["Aa", "Bb", "12,345", "_"]

// 알파벳, 숫자, 언더스코어가 아닌 문자 또는 ','가 한 번 이상 반복되는 문자열을 전역 검색
regExp = /[\W,]+/g;

target.match(regExp); // -> [" ", " ", ",", " $%&"]
  • 알파벳, 숫자, 언더스코어를 의미
  • \W\w와 반대로 알파벳, 숫자, 언더스코어가 아닌 문자를 의미한다.

31.5.5 NOT 검색

1
2
3
4
5
6
const target = 'AA BB 12 Aa Bb';

// 숫자를 제외한 문자열을 전역 검색한다.
const regExp = /[^0-9]+/g;

target.match(regExp); // -> ["AA BB ", " Aa Bb"]
  • [...] 내의 ^은 not의 의미가 있다.
  • \D[^0-9]와 같다.
  • \W[^A-Za-z0-9_]와 같다.

31.5.6 시작 위치로 검색

1
2
3
4
5
6
const target = 'https://poiemaweb.com';

// 'https'로 시작하는지 검사한다.
const regExp = /^https/;

regExp.test(target); // -> true
  • [...] 밖의 ^은 문자열의 시작을 의미

31.5.7 마지막 위치로 검색

1
2
3
4
5
6
const target = 'https://poiemaweb.com';

// 'com'으로 끝나는지 검사한다.
const regExp = /com$/;

regExp.test(target); // -> true
  • $는 문자열의 마지막을 의미

31.6 자주 사용하는 정규표현식

31.6.1 특정 단어로 시작하는지 검사

다음 예제는 검색 대상 문자열이 http:// 또는 https://로 시작하는지 검사한다.

1
2
3
4
5
6
const url = 'https://example.com';

// 'http://' 또는 'https://'로 시작하는지 검사한다.
/^https?:\/\//.test(url); // -> true

/^(http|https):\/\//.test(url); // -> true

31.6.2 특정 단어로 끝나는지 검사

다음 예제는 검색 대상 문자열이 html로 끝나는지 검사한다.

1
2
3
4
const fileName = 'index.html';

// 'html'로 끝나는지 검사한다.
/html$/.test(fileName); // -> true

31.6.3 숫자로만 이루어진 문자열인지 검사

1
2
3
4
const target = '12345';

// 숫자로만 이루어진 문자열인지 검사한다.
/^\d+$/.test(target); // -> true

31.6.4 하나 이상의 공백으로 시작하는지 검사

1
2
3
4
const target = ' Hi!';

// 하나 이상의 공백으로 시작하는지 검사한다.
/^[\s]+/.test(target); // -> true
  • \s: 스페이스, 탭 등 여러 가지 공백 문자를 의미
    • [\t\r\n\v\f]와 같은 의미

31.6.5 아이디로 사용 가능한지 검사

다음 예쩨는 검색 대상 문자열이 알파벳 대소문자 또는 숫자로 시작하고 끝나며, 4~10자리인지 검사한다.

1
2
3
4
const id = 'abc123';

// 알파벳 대소문자 또는 숫자로 시작하고 끝나며 4 ~ 10자리인지 검사한다.
/^[A-Za-z0-9]{4,10}$/.test(id); // -> true

31.6.6 메일 주소 형식에 맞는지 검사

1
2
3
const email = 'ungmo2@gmail.com';

/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/.test(email); // -> true
  • *: 0 or more

31.6.7 핸드폰 번호 형식에 맞는지 검사

1
2
3
const cellphone = '010-1234-5678';

/^\d{3}-\d{3,4}-\d{4}$/.test(cellphone); // -> true

31.6.8 특수 문자 포함 여부 검사

1
2
3
4
const target = 'abc#123';

// A-Za-z0-9 이외의 문자가 있는지 검사한다.
(/[^A-Za-z0-9]/gi).test(target); // -> true
  • 특수 문자를 선택적으로 검사하기 위해 다음 방식을 사용 가능

    1
    
      (/[\{\}\[\]\/?.,;:|\)*~`!^\-_+<>@\#$%&\\\=\(\'\"]/gi).test(target); // -> true
    
  • 특수 문자를 제거할 때는 String.prototype.replace 메서드를 사용

    1
    
      target.replace(/[^A-Za-z0-9]/gi, ''); // -> abc123
    
This post is licensed under CC BY 4.0 by the author.