seongkyu.log
📖
자바스크립트

자바스크립트 정규표현식

2022.12.30

자바스크립트 정규표현식

코드를 짜다보면 전화번호, 이메일 등의 체크 형식에서 정규표현식을 종종 사용하는 경우가 있는 데, 한눈에 봤을 때 코드를 이해하기 어려운 경우가 종종있었다. 어떤 방식으로 정규표현식을 작성하는지 알아보기 위해 공부해보았다.

정규표현식

정규 표현식(regular expression)은 문자 검색과 교체에 사용되는 패턴이다. 자바스크립트에서는 RegExp 객체와 문자열 메서드를 조합하여 정규표현식을 사용할 수 있다.

  • 정규 표현식은 패턴과 선택적으로 사용할 수 있는 플래그로 구성된다.

  • 정규식 객체를 만들 때는 두 가지 문법이 사용된다.

    1. 긴 문법
      • 긴 문법은 아래와 같이 사용한다.
    regexp = new RegExp('pattern', 'flags');
    1. 짧은 문법
      • 짧은 문법은 /를 사용한다.
    regexp = /pattern/; // 플래그가 없음
    regexp = /pattern/gim; // 플래그 g, m, i 가 있음
  • /는 자바스크립트에 정규 표현식을 생성하고 있다는 것을 알린다. 문자열에 따옴표를 쓰는 것과 동일한 역할

  • 짧은 문법이든 긴 문법이든 상관없이 regexp는 내장 클래스 RegExp의 인스턴스가 된다.

  • 단, 두 문법의 차이점은 /…/를 사용하면 문자열 템플릿 리터럴에서 ${…}를 사용했던 것처럼 중간에 표현식을 넣을 수 없다. 슬래시를 사용한 방법은 완전히 정적이기 때문이다.

  • 짧은 문법을 사용할 때는 코드를 작성하는 시점에 패턴을 알고 있을 때 사용한다. 반면 긴 문법은 상황에 따라 동적으로 생성된 문자열을 가지고 정규 표현식을 만들어야 할 때 주로 사용한다.

let tag = prompt('어떤 태그를 찾고 싶은가요?', 'h2');
let regexp = new RegExp(`<${tag}>`); // 프롬프트에서 'h2'라고 대답한 경우, /<h2>/와 동일한 역할을 한다.
플래그
  • 정규 표현식에는 검색에 영향을 주는 플래그를 선택적으로 붙일 수 있다.
  • 자바스크립트에서는 6개의 플래그를 지원한다.
  • pattern:i : i플래그가 붙으면 대소문자 구분없이 검색한다. Ignore case
  • pattern:g : g플래그가 붙으면 패턴과 일치하는 모든 것들을 찾는다. g가 없으면 패턴과 일치하는 첫 번째 결과만 반환된다. Global
  • pattern:m : 다중 행 모드(multiline mode)를 활성화한다.(여러행 검색)
  • pattern:s : pattern:.이 개행문자 \n도 포함하도록 dotail 모드를 활성화한다.
  • pattern:u : 유니코드 전체를 지원한다. 이 플래그를 사용하면 서로게이트 쌍을 올바르게 처리할 수 있다.
  • pattern:y : 문자 내 특정 위치에서 검색을 진행하는 sticky 모드를 활성화 시킨다.
str.match로 검색하기
  • str.match(regexp)에는 3가지 모드가 있다.
  1. 정규 표현식에 플래그 pattern:g가 붙으면 패턴과 일치하는 모든 것을 담은 배열을 반환
let str = 'We will, we will rock you';
alert(str.match(/we/gi)); // We, we
/**
 * g : 패턴과 일치하는 모든것
 * i : 대소문자 구분 없음
 * /
  1. 플래그 pattern:g가 붙지 않은 경우에는 패턴에 맞는 첫 번째 부분 문자열만 담은 배열을 반환. 해당 문자열은 배열 인덱스 0에 저장되는데, 문자열의 프로퍼티에는 상세한 추가 정보가 저장된다.
let str = 'We will, we will rock you';
let result = str.match(/we/i);
alert(result[0]); // We
alert(result.length); // 1
alert(result.index); // 0 (부분 문자열의 위치)
alert(result.input); // We will, we will rock you (원본문자열 )
  • 정규 표현식을 괄호로 둘러싼 경우에는 메서드 호출 시 반환되는 배열에 0이외에도 다른 인덱스가 있을 수 있음
  1. pattern:g의 유무와 상관없이 패턴과 일치하는 부분 문자열을 찾지 못한 경우에는 null이 반환된다.
let matches = 'JavaScript'.match(/HTML/); // matches에는 null이 저장
if (!matches.length) {
  // TypeError
  //code
}
  • str.match 호출 결과가 항상 배열이 되게 하려면 아래와 같이 사용한다.
let matches = 'JavaScript'.match(/HTML/) || [];
if (!matches.legnth) {
  alert('정규 표현식과 일치하는 부분 문자열이 없다.');
}
str.replace로 치환
  • str.replace(regexp, replacement)를 사용하면 regexp에 일치하는 부분 문자열을 replacement로 교체할 수 있다.
console.log('We will, we will'.replace(/we/i, 'I')); // I will, we will
  • replacement는 문자열인데, 문자열 안에 아래 특수문자를 넣으면 독특한 방식으로 문자열을 교체할 수 있다.

  • $& : 패턴과 일치하는 부분 문자열

  • $` : 문자열 일부를 일치 전에 삽입

  • $’ : 문자열 일부를 일치 후에 삽입

  • $n : n이 1~2자리 숫자일 경우, n번째 괄호 내용을 삽입

  • $$ : $문자를 삽입

regexp.test로 일치 여부 확인하기
  • 패턴과 일치하는 부분 문자열이 하나라도 있는경우 true, 아니면 false를 반환한다.
let str = 'I love JavaScript';
let regexp = /LOVE/i;
alert(regexp.test(str)); // true

문자클래스

  • 문자 클래스는 특정 집합에 포함된 모든 기호에 일치하는 특별한 표현이다.

  • 문자 클래스에는 다음과 같은 클래스가 있다.

  • pattern:\d : 숫자

  • pattern:\D : 숫자가 아닌 문자

  • pattern:\s : 스페이스, 탭, 줄 바꿈 문자

  • pattern:\S : 스페이스, 탭, 줄바꿈문자를 제외한 모든 문자

  • pattern:\w : 라틴문자, 숫자, 밑줄_

  • pattern:\W : 라틴문자, 숫자, 밑줄을 제외한 모든 문자

  • pattern:. : 정규표현식 ’s’플래그가 있으면 모든 문자, 없으면 줄바꿈을 제외한 모든 문자

let str = '+7(903)-123-45-67';
let regexp = /\d/;
alert(str.match(regexp)); // 7 , 가장 먼저 만난 숫자가 7
let regexp2 = /\d/g;
console.log(str.match(regexp2)); //['7', '9', '0', '3', '1', '2', '3', '4', '5', '6', '7']
console.log(str.match(regexp).join('')); // 79035419441
  • 정규 표현식에 일반 기호와 문자 클래스를 같이 사용할 수 있다.
let str = 'Is there CSS4?';
let regexp = /CSS\d/;
console.log(str.match(regexp)); // CSS4
  • 문자 클래스를 여러개 사용할 수도 있다.
console.log('I love HTML5'.match(/\s\w\w\w\w\d/)); // 'HTML5'
반대 클래스
  • 모든 문자 클래스에는 반대클래스가 있다. 같은 글자로 표기하지만 대문자를 사용한다.
  • 반대란 해당 문자를 제외한 모든 문자에 일치한다.
  • 패턴 d,D / 패턴 s,S / 패턴 w,W
let str = '+7(903)-123-45-67';
alert(str.replace(/\D/g, '')); // 숫자가 아닌 문자를 찾아 문자열에서 없애버리는 것
점은 아무문자에나 일치
  • pattern : .은 줄 바꿈 문자를 제외한 모든 문자와 일치하는 특별한 문자 클래스이다.
alert('Z'.match(/./)); // Z

let regexp = /CS.4/;
alert('CSS4'.match(regexp)); // CSS4
alert('CS 4'.match(regexp)); // CS 4 (공백도 문자이기때문에 출력된다)
alert('CS4'.match(/CS.4/)); // null, 점과 일치하는 문자가 없기 때문에
s플래그와 점을 사용하여 모든 문자 찾기
  • 기본적으로 점은 \n과 일치하지 않음
  • pattern:s를 사용하면 점은 모든 문자와 일치
alert('A\nB'.match(/A.B/)); // null
alert('A\nB'.match(/A.B/s)); // A\nB
유니코드 : u플래그와 \p{…}클래스
  • pattern:u플래그로 정규 표현식에서 유니코드 기능을 활성화할 수 있다.

    • 4바이트 문자를 2바이트 문자 2개로 처리하지 않고 문자 한 개로 올바르게 처리한다.
    • \p{…}를 이용하여 유니코드 프로퍼티를 검색에 사용할 수 있다.
  • 유니코드 프로퍼티를 사용하면 특정 단어의 단어, 따옴표나 통화 단위같은 특수 문자 등을 모두 검색할 수 있다.

  • 자바스크립트는 문자열에 유니코드 인코딩을 사용한다.

    • 대부분의 문자는 2바이트로 인코딩되어 있는데, 이것으로는 65,536개 까지만 표현할 수 있다. 따라서 일부 문자는 4바이트로 인코딩되어있다.
  • 문자는 하나인데 길이가 2가 나오는 경우

  • length는 4바이트 문자를 2바이트 문자 2개로 취급. 4바이트를 하나로 묶어서 취급해야 하므로 올바르지 않은 결과이다. (서로게이트 쌍)

alert('😄'.length); // 2
alert('𝒳'.length); // 2
  • 기본적으로는 정규표현식도 4바이트의 긴 문자를 2바이트 문자 2개로 취급한다. 문자열의 경우처럼 이런 방식은 잘못된 결과로 이어질 수 있다.

  • 문자열과 다르게 정규표현식에는 이런 문제를 해결할 수 있는 pattern:u플래그가 있다. 이를 사용하면 유니코드 프로퍼티를 사용한 검색이 가능해진다.

  • pattern:\p{…}를 사용하면 프로퍼티를 통해 문자를 찾을 수 있다. 이를 사용하기 위해서는 정규 표현식에 pattern:u플래그가 반드시 있어야 한다.

let str = 'A ბ ㄱ';

alert(str.match(/\p{L}/gu)); // A,ბ,ㄱ
alert(str.match(/\p{L}/g)); // null ('u' 플래그가 없어서 일치 결과 없음)
  • 다음은 주요 문자 범주와 각각의 하위 범주 목록

  • 문자(Letter) L

    • 소문자(lowercase)Ll
    • 조정(modifier)Lm
    • 단어의 첫글자를 대문자로(titlecase)Lt
    • 대문자(uppercase)Lu
    • 기타(other)Lo
  • 숫자(Number) N

    • 10진수(decimal digit)Nd
    • 문자(letter number)Nl
    • 기타(other)No
  • 문장 부호(Punctuation) P

    • 연결선(connector) Pc
    • 대시(dash) Pd
    • 처음 따옴표(initial quote) Pi
    • 마지막 따옴표(final quote) Pf
    • 열기(open) Ps
    • 닫기(close) Pe
    • 기타(other) Po
  • 표시(Mark) M(강세 등)

    • 간격 결합(spacing combining) Mc
    • 묶음(enclosing) Me
    • 비공백(non-spacing) Mn
  • 기호(Symbol) S

    • 통화(currency) Sc
    • 수정(modifier) Sk
    • 수학(math) Sm
    • 기타(other) So
  • 구분 기호(Separator) Z

    • 줄(line) Zl
    • 단락(paragraph) Zp
    • 공백(space) Zs
  • 기타(other) C

    • 제어(control) Cc
    • 형식(format) Cf
    • 할당되지 않음(not assigned) Cn
    • 사용자 지정(private use) Co
    • 서로게이트(surrogate) Cs
  • 소문자를 찾을 때 pattern:\p{Ll}, 문장부호를 찾을 때pattern:\p{P}등으로 검색할 수 있다.

  • 참고할 수 있는 문서

앵커 : 문자열의 시작 ^과 끝 $
  • 캐럿(caret) 기호 pattern:^와 달러기호 pattern:$는 정규식에서 앵커라는 뜻을 지닌다.
  • 캐럿기호는 텍스트의 시작, 달러기호는 텍스트의 끝을 나타낸다.
// ^Mary ==> 문자열이 Mary로 시작하는지 검사
// snow$ ==> 문자열이 snow로 끝나는지 검사
let str = 'Mary and a little lamb';
alert(/snow$/.test(str)); // true
  • pattern:^…$는 문자열이 패턴과 완전히 일치하는지 확인할 때 자주 사용된다. 사용자 입력 내용이 올바른 형식으로 되어있는지 확인할 때가 대표적인 예
  • 문자열 전체가 이 형식에 일치해야 한다. 형식에서 벗어난 문자가 있거나 문자가 더 많으면 false를 출력한다.
let goodInput = '12:34';
let badInput = '12:345';
let regexp = /^\d\d:\d\d$/;
alert(regexp.test(goodInput)); // true
alert(regexp.test(badInput)); // false
m플래그
  • pattern:m플래그를 사용하면 여러 행 모드(multiline mode)를 활성화할 수 있음
  • 여러 행 모드는 pattern:^, pattern:$의 작동방식에만 영향을 준다.
  • 전체 문자열의 처음/끝 뿐만아니라 각 행의 시작/끝에도 대응한다.
let str = `1st place: Winnie
2nd place: Piglet
3rd place: Eeyore`;
alert(str.match(/^\d/gm)); // 1, 2, 3
alert(str.match(/^\d/g)); // 1 , m플래그가 없으면 맨 앞 숫자만 검색된다.

let str = `Winnie: 1
Piglet: 2
Eeyore: 3`;

alert(str.match(/\d$/gm)); // 1,2,3
  • 줄 바꿈을 찾을 때 pattern:^, pattern:$뿐만아니라 \n도 사용할 수 있다.
let str = `Winnie: 1
Piglet: 2
Eeyore: 3`;

alert(str.match(/\d\n/gm)); // 1,2
/*
3뒤에는 줄바뀜문자가 없어서 미출력됨. 
*/
정규식에서 쓰이는 메서드
  1. exec

    • 대응되는 문자열을 찾는 RegExp 메서드
    • 대응되는 문자열을 찾으면 정보를 갖고있는 배열을 반환, 찾지 못하면 null 을 반환
  2. test

    • 대응되는 문자열이 있는지 검사하는 RegExp 메서드
    • 대응되는 문자열을 찾으면 true, 아니면 false를 반환
  3. match

    • 대응되는 문자열을 찾는 String 메서드
    • 대응되는 문자열을 찾으면 갖고있는 배열을 반환, 찾지 못하면 null을 반환
  4. search

    • 대응되는 문자열이 있는 검사하는 String 메서드
    • 대응된 부분의 인덱스를 반환, 찾지 못하면 -1을 반환
  5. replace

    • 대응되는 문자열을 찾아 다른 문자열로 치환하는 String 메서드
  6. split

    • 정규식 혹은 문자열로 대상 문자열로 나누어 배열로 반환하는 String 메서드
정규식 검색 기준 패턴
  • | : OR. a|b식으로 사용
  • [] : 괄호안의 문자들중 하나. or 처리 묶음
    • /[abc]/ : a or b or c 를 포함하는
    • [다-바] : 다 or 라 or 마 or 바
  • [^문자] : 괄호안의 문자를 제외한 것
    • [^lgen] ‘l’ ‘g’ ‘E’ ‘n’ 4개 문자를 제외
  • ^문자열 : 특정 문자열로 시작
    • /^www/
  • 문자열$ : 특정 문자열로 끝남
    • /com$/
정규표현식 수량 패턴
  • 어떠한 패턴이 얼만큼 등장하는지

  • * : 0개 이상 나타나는 문자

    • a*b : a가 앞에 있을 수도 있고, 여러개 있을 수도 있고 b도 뒤에 있을 수도 있고, 여러 개 있을 수도 있음. ‘aab’,‘ab’ 모두 가능하다
  • + : 1개 이상 나타나는 문자

    • a+b : a가 한개이상, b도 한개 이상 있어야한다. ‘ab’, ‘aabb’, ‘abb’ ..
  • ? : 없거나 1개인 경우

    • a?b : a가 없거나 1개, b가 없거나 1개. ‘b’, ‘ab’..
  • {m,n} : m회 이상 n회 이하 나타나는 문자

    • [els]{1,3} : e or l or s 가 1개 이상 3개 이하
👇 도움이 되셨다면 👇

© Powered by danmin