[31장] RegExp(정규표현식)

junjeong·2023년 10월 16일
0
post-thumbnail

writed by johan

..들어가며

정규 표현식(Regular Expression, 줄여서 Regex 또는 Regexp)은 문자열에서 패턴을 찾거나 조작하기 위해 사용되는 형식 언어이다. 정규 표현식은 문자열 검색, 대체, 추출 등 다양한 작업에 유용하며, 다양한 프로그래밍 언어와 텍스트 편집기에서 지원된다. 자바스크립트는 펄(Pearl)의 정규 표현식 문법을 ES3부터 도입했다.

정규 표현식의 생성

정규 표현식 객체(RegExp 객체)를 생성하기 위해서는 두 가지 방법을 사용할 수 있다.

  1. 정규 표현식 리터럴
  2. RegExp 생성자 함수

일반적으로 정규 표현식 리터럴을 사용한다.

정규 표현식 리터럴은 다음과 같이 표현한다.

/regex/i
/: 시작, 종료 기호
regex: 패턴
i: 플래그

플래그(flag)

i (Ignore case)

대소문자를 구별하지 않고 패턴을 검색한다.

g (Global)

전역 검색을 수행한다. 이 플래그가 없으면 문자열에서 첫 번째 매치만 찾는다.

m (Multi-line)

여러 줄에 걸친 검색을 수행한다. 이 플래그가 설정되면, '^'와 '$' 메타문자는 문자열의 시작과 끝뿐 아니라 각 줄의 시작과 끝에도 일치하게 된다.

메서드

RegExp.prototype.test

문자열 검색: test() 메서드를 사용하여 문자열에 특정 패턴이 있는지 확인할 수 있다.

const regex = /hello/;
const str = 'hello world';
console.log(regex.test(str)); // true

String.prototype.replace

문자열 치환: replace() 메서드를 사용하여 문자열에서 정규표현식에 해당하는 부분을 다른 문자열로 바꿀 수 있다.

const regex = /world/g;
const str = 'hello world, world';
console.log(str.replace(regex, 'JavaScript')); // "hello JavaScript, JavaScript"

RegExp.prototype.exec

문자열 추출: exec() 메서드를 사용하여 문자열에서 정규표현식에 해당하는 부분을 추출할 수 있다.

const regex = /is/g;
const str = 'Is this all there is?';
console.log(regex.exec(str));
// ['is', index: 5, input: 'Is this all there is?', groups: undefined]

exec 메서드는 문자열 내의 모든 패턴을 검색하는 g 플래그를 지정해도 첫 번째 매칭 결과만 반환한다. 하지만 String.prototype.match 메서드는 g 플래그가 지정되면 모든 매칭 결과를 배열로 반환한다.

String.prototype.match

문자열 추출: match() 메서드를 사용하여 문자열에서 정규표현식에 해당하는 부분을 추출할 수 있다.

const regex = /\\d+/g; // 숫자에 해당하는 부분을 전역적으로 찾는 정규표현식
const str = '123 abc 456 def';
console.log(str.match(regex)); // ["123", "456"]

이처럼 다양한 방법으로 정규 표현식을 활용할 수 있으며, 이 외에도 많은 기능들이 존재한다.

만약 정규 표현식을 사용하지 않는다면 반복문과 조건문을 통해 한 문자씩 연속해서 체크해야 하는 번거로움이 있다.

메타문자(meta-character)

정규 표현식에서 메타문자(meta-character)란 특별한 의미를 가진 문자를 말한다. 메타문자들은 패턴을 정의할 때 사용되며, 문자열 내에서 특정 위치, 문자 집합, 또는 반복 등을 나타낸다.

[ ] (Square brackets)

[] 는 일치하는 문자들의 집합을 지정하기 위해 사용한다. 대괄호 안에 있는 어떤 문자라도 일치하는 것을 찾는다.

let regex = /[aeiou]/g;
let str = "Hello, how are you?";
let match;

while ((match = regex.exec(str)) !== null) {
    console.log(`Found ${match[0]} at position ${match.index}`);
}

위의 코드에서 정규표현식 /[aeiou]/g는 'a', 'e', 'i', 'o', 'u' 중 어느 것이라도 일치하는 문자를 찾는다. 따라서 "Hello, how are you?" 내의 모든 모음이 매칭된다.

Found e at position 1
Found o at position 4
Found o at position 7
Found a at position 10
Found e at position 12
Found o at position 15
Found u at position 18

. (Period)

.임의의 단일 문자와 일치한다. 즉, 어떤 문자든지와 일치할 수 있다. (단, 줄바꿈 문자 제외).

예를 들어 /a.b/라는 정규표현식은 'a'와 'b' 사이에 어떤 한 글자가 있는 경우와 매칭된다 (예: "acb", "a$b", "a9b" 등).

^ (Caret)

^는 문자열이나 행이 (멀티라인 모드일 경우) 특정 패턴으로 시작하는지 검사할 때 사용된다.

let regex = /^cat/g;
let str1 = "cat is on the mat";
let str2 = "the cat is on the mat";

console.log(regex.test(str1));  // true
console.log(regex.test(str2));  // false

참고로 [ … ] 내의 ^은 not의 의미를 갖는다. 예를 들어, [^0-9]는 숫자를 제외한 문자를 의미한다.

const target = 'AA BB 12 Aa Bb';

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

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

$ (Dollar)

$는 문자열이나 행이 (멀티라인 모드일 경우) 특정 패턴으로 끝나는지 검사할 때 사용된다.

let regex = /end$/g;
let str1 = "This is the end";
let str2 = "The end is near";

console.log(regex.test(str1));  // true
console.log(regex.test(str2));  // false

* (Asterisk)

*앞선 요소가 0번 이상 반복되는 부분과 일치한다.

let regex = /ca*r/g;
let str = "cr car caar caaar";
let match;

while ((match = regex.exec(str)) !== null) {
    console.log(`Found ${match[0]} at position ${match.index}`);
}

위의 코드에서 정규표현식 /ca*r/g는 'c'로 시작하고 'r'로 끝나며, 그 사이에 'a'가 0번 이상 반복되는 문자열을 찾는다. 따라서 "cr", "car", "caar", "caaar" 등이 모두 매칭된다. 실행 결과는 다음과 같다.

Found cr at position 0
Found car at position 3
Found caar at position 7
Found caaar at position 12

+ (Plus)

+앞선 요소가 1번 이상 반복되는 부분과 일치한다.

let regex = /ca+r/g;
let str = "cr car caar caaar";
let match;

while ((match = regex.exec(str)) !== null) {
    console.log(`Found ${match[0]} at position ${match.index}`);
}

위의 코드에서 정규표현식 /ca+r/g는 'c'로 시작하고 'r'로 끝나며, 그 사이에 'a'가 1번 이상 반복되는 문자열을 찾는다.

Found car at position 3
Found caar at position 7
Found caaar at position 12

? (Question mark)

?앞선 요소가 0번 또는 1번 반복되는 부분과 일치한다.

let regex = /ca?r/g;
let str = "cr car caar";
let match;

while ((match = regex.exec(str)) !== null) {
    console.log(`Found ${match[0]} at position ${match.index}`);
}

위의 코드에서 정규표현식 /ca?r/g는 'c'로 시작하고 'r'로 끝나며, 그 사이에 'a'가 없거나 1번 있는 문자열을 찾는다. 따라서 "cr"와 "car"가 매칭된다.

Found cr at position 0
Found car at position 3

\d, \w, \s

\d\w\s는 숫자, 단어 문자(알파벳, 숫자, 밑줄), 공백 문자와 각각 일치한다.

let regex = /\d\w\s/g;
let str = "1a 2b 3c 4d";
let match;

while ((match = regex.exec(str)) !== null) {
    console.log(`Found ${match[0]} at position ${match.index}`);
}

위의 코드에서 정규표현식 /\d\w\s/g는 숫자(\d), 단어 문자(\w), 그리고 공백 문자(\s) 순서로 나타나는 패턴을 찾는다. 따라서 “4d”를 제외한 "1a ", "2b ", "3c "가 매칭된다.

Found 1a  at position 0
Found 2b  at position 4
Found 3c  at position 8

\D, \W, \S

\D\W\S: 숫자가 아닌 것, 단어 문자가 아닌 것(특수문자 등), 공백이 아닌 것과 각각 일치한다.

let regex = /\D\W\S/g;
let str = "a#1 b@2 c&3";
let match;

while ((match = regex.exec(str)) !== null) {
    console.log(`Found ${match[0]} at position ${match.index}`);
}

위의 코드에서 정규표현식 /\D\W\S/g는 숫자가 아닌 문자(\D), 단어 문자가 아닌 문자(\W), 그리고 공백이 아닌 문자(\S) 순서로 나타나는 패턴을 찾습니다. 따라서 "a#1", "b@2", "c&3" 모두 매칭된다.

Found a#1 at position 0
Found b@2 at position 4
Found c&3 at position 8

( ) (Group)

( ): 그룹을 만든다. 그룹 안에 있는 모든 것은 하나의 단위로 취급한다.

let regex = /ca+r/g;
let str = "cr ccar car caar caaar";
let match;

while ((match = regex.exec(str)) !== null) {
    console.log(`Found ${match[0]} at position ${match.index}`);
}

위의 코드에서 정규표현식 /(ca)+r/g는 'ca'가 1번 이상 반복되고 'r'로 끝나는 문자열을 찾는다. 따라서 "car", "caar", "caaar" 등이 매칭된다.

Found car at position 3
Found caar at position 7
Found caaar at position 12

\ (Backslash)

정규 표현식에서 백슬래시 \는 특수 문자를 이스케이프 하는데 사용된다. 즉, 정규 표현식에서 특별한 의미를 가지는 문자를 일반 문자로 처리하게 한다.

let regex = /ca\+r/g;
let str = "cr car ca+r";
let match;

while ((match = regex.exec(str)) !== null) {
    console.log(`Found ${match[0]} at position ${match.index}`);
}

위의 코드에서 정규표현식 /ca\+r/g는 'c', 'a', '+', 'r' 순서로 나타나는 문자열을 찾는다. 따라서 "ca+r"가 매칭된다. 하지만 "cr", "car"은 중간에 '+'가 없으므로 매칭되지 않는다.

Found ca+r at position 7

| (Alternation)

정규 표현식에서 파이프 '|'는 OR 연산자로 작동하며, 두 패턴 중 하나와 일치하는 문자열을 찾는다.

let regex = /cat|dog/g;
let str = "I have a cat and a dog.";
let match;

while ((match = regex.exec(str)) !== null) {
    console.log(`Found ${match[0]} at position ${match.index}`);
}

위의 코드에서 정규표현식 /cat|dog/g는 'cat' 또는 'dog'와 일치하는 문자열을 찾는다. 따라서 "cat"과 "dog" 모두 매칭된다.

Found cat at position 9
Found dog at position 18

{ } (Curly brackets)

{ }: 특정 패턴이 반복되는 횟수를 지정하는데 사용된다.

  • {n}: 바로 앞의 요소가 정확히 n번 반복되어야 함을 의미한다.
  • {n,}: 바로 앞의 요소가 최소한 n번 반복되어야 함을 의미한다.
  • {n,m}: 바로 앞의 요소가 최소 n번 이상, 최대 m번 이하 반복되어야 함을 의미한다.
profile
Whether you're doing well or not, just keep going👨🏻‍💻🔥

0개의 댓글