Post

[JS] 정규표현식

[JS] 정규표현식

알고리즘 기초 문제들을 풀면서 정규표현식 관련된 문제에서 어려움을 느끼고, 해결법에 잘 접근하지 못한다는 것을 알았습니다. 그래서 관련 문제를 풀면서 정규표현식을 익히고자 합니다 :)


정규 표현식이란?

문자열에서 특정 문자 조합을 찾기 위한 패턴

  • 정규 표현식은 문자열 대상으로 패턴 매칭 기능을 제공한다.

정규 표현식의 생성

1. 정규 표현식 리터럴

정규식 구성 코드는 패턴과 플래그로 구성된다.

1
2
3
4
const target = "Is this all there is?";
// 패턴 : is, 플래그 : i => 대소문자 구별 X
const regexp = /is/i;
regexp.text(target); // true;

2. RegExp 생성자 함수

  • pattern : 정규 표현식의 패턴
  • flags : 정규 표현식의 플래그 (g, i, m, u, y)
    1
    
    new RegExp(pattern[, flags]);
    
1
2
3
4
const target = "Is this all there is?";
// 패턴 : is, 플래그 : i => 대소문자 구별 X
const regexp = new RegExp(/is/i);
regexp.text(target); // true;

변수를 사용해 동적으로 RegExp 객체를 생성할 수 있다.

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

정규식 메서드

메서드의미
("문자열").match(/정규표현식/플래그)“문자열”에서 “정규표현식”에 매칭되는 항목들을 배열로 반환
("문자열").replace(/정규표현식/, "대체문자열")“정규표현식”에 매칭되는 항목을 “대체문자열”로 변환
("문자열").split(정규표현식)“문자열”을 “정규표현식”에 매칭되는 항목으로 쪼개어 배열로 반환
("문자열").search(정규표현식) 
(정규표현식).test("문자열")“문자열”이 “정규표현식”과 매칭되면 true, 아니면 false 반환
(정규표현식).exec("문자열")“정규표현식”에 매칭되는 항목들을 배열로 반환 (단, 무조건 첫 번째 매칭 결과만 반환)

RegExp.prototype.exec

1
2
3
4
5
6
7
8
9
// 정규표현식을 담은 변수
const regex = /apple/; // apple 이라는 단어가 있는지 필터링
const txt = "Hello banana and apple hahahaha";
txt.match(regex); // ['apple']
txt.replace(regex, "watermelon"); // 'Hello banana and watermelon hahahaha'

regex.test(txt); // true
regex.exec(txt); // ['apple', index: 4, input : "Hello banana and apple hahahaha"]

** g플래그를 지정해도 첫번째 결과만 반환 **

📌 정규식 플래그

정규식 플래그는 정규식을 생성할 때 검색 방식을 설정하기 위해 사용한다.

FlagMeaningDesc
i ⭐️⭐️⭐️Ignore Case대소문자를 구별하지 않고 검색
g ⭐️⭐️⭐️Global패턴과 일치하는 모든 문자열을 전역 검색
m ⭐️⭐️⭐️Multi Line문자열의 행이 바뀌더라도 검색을 계속한다.
s .​(모든 문자 정규식)이 개행 문자 \n도 포함하도록
uunicode유니코드 전체를 지원
ysticky문자 내 특정 위치에서 검색을 진행하는 ‘sticky’ 모드를 활성화
1
2
3
4
5
6
const target = "Is this all there is?";

target.match(/is/); // ['is', index: 5, input: 'Is this all there is?', groups: undefined]
target.match(/is/i); // ['Is', index: 0, input: 'Is this all there is?', groups: undefined]
target.match(/is/g); // ['is', 'is']
target.match(/is/ig); // ['Is', 'is', 'is']

📌 정규식 패턴

1
2
리터럴 문자 (정규 문자) : 일반 문자, \0, \n, \t, \v, \f, \r, \xhh, \uhhhh, \cX
메타 문자 (정규 표현식의 구문 문자) : ^ $ \ . * + ? ( ) [ ] { } |_

✅ 기본 문자

기호설명예제매칭 결과
a-zA-Z영어알파벳(-으로 범위 지정)  
ㄱ-ㅎ가-힣한글 문자(-으로 범위 지정)  
0-9숫자(-으로 범위 지정)  
.임의의 문자 한 개/a.b/"acb", "a8b" (✔), "ab", "abb" (❌)
\d숫자 ([0-9]와 동일)/\d+/"abc123""123"
\D숫자가 아닌 문자 ([^0-9]와 동일)/\D+/"abc123""abc"
\w단어 문자 ([a-zA-Z0-9_])/\w+/"hello_123!""hello_123"
\W단어 문자가 아닌 문자 ([^a-zA-Z0-9_])/\W+/"hello_123!""!"
\s공백 (\t, \n, \r 포함)/\s+/"hello world"" "
\S공백이 아닌 문자/\S+/"hello world""hello"

✅ 반복 패턴

기호설명예제매칭 결과
*0개 이상 반복 ({0,})/go*d/"gd", "god", "good", "goood" (✔)
+1개 이상 반복 ({1,})/go+d/"god", "good", "goood" (✔), "gd" (❌)
?0개 또는 1개 ({0,1})/go?d/"gd", "god" (✔), "good" (❌)
{n}정확히 n개 반복/a{3}/"aaa" (✔), "aa" (❌)
{n,}최소 n개 반복/a{2,}/"aa", "aaa", "aaaa" (✔)
{n,m}n개 이상, m개 이하 반복/a{2,4}/"aa", "aaa", "aaaa" (✔), "a", "aaaaa" (❌)

✅ 검색 패턴

기호설명예제매칭 결과
|OR/apple|banana/"I like apple" (✔), "I like banana" (✔)
[]문자 클래스 (괄호 안의 문자 중 하나)/[aeiou]/"apple""a" (✔)
[^문자]부정 문자 클래스 (괄호 안의 문자 제외)/[^0-9]/"hello123""h" (✔)
^문자열의 시작/^hello/"hello world" (✔), "world hello" (❌)
$문자열의 끝/world$/"hello world" (✔), "world hello" (❌)
\b그룹 검색(분류X)/\bcat\b/"cat is here" (✔), "caterpillar" (❌)
\B단어의 처음/끝이 아님/\Bcat\B/"caterpillar" (✔), "cat " (❌)
\n그룹 참조 (n번째 그룹)/(\d+)-\1/"123-123" (✔), "123-456" (❌)

✅ 그룹 패턴 (꽤 난이도가 있는 표현식)

기호설명예제매칭 결과
()그룹 검색 및 분류(match메서드에서 그룹별로 묶어줌)/(go)+d/"gogod", "gogogod" (✔)
(? : 패턴)캡처하지 않는 그룹/(?:go)+d/그룹 참조 없이 "gogod" (✔)
(?=...)긍정형 전방 탐색 (앞에 특정 패턴이 있는지 확인)/\d(?=px)/"10px""0" (✔)
(?!...)부정형 전방 탐색 (앞에 특정 패턴이 없는지 확인)/\d(?!px)/"10px""1" (✔)
(?<=...)긍정형 후방 탐색 (뒤에 특정 패턴이 있는지 확인)/(?<=\$)\d+/"$100""100" (✔)
(?<!...)부정형 후방 탐색 (뒤에 특정 패턴이 없는지 확인)/(?<!\$)\d+/"100""100" (✔), "$100" (❌)

6. 특수 기호 & 플래그

기호설명예제매칭 결과
\이스케이프 문자/\./"hello.world""." (✔)
g글로벌 검색 (전체 검색)/is/g"this is"["is", "is"]
i대소문자 구분 없음/hello/i"HELLO" (✔)
m여러 줄 모드 (^, $가 줄 단위 적용)/^hello/m"hello\nworld""hello" (✔)
s.이 개행 문자 포함/hello.world/s"hello\nworld" (✔)

알고리즘 풀이 - 프로그래머스 Lv.2 - [3차] 파일명 정렬

프로그래머스 Lv2. 파일명 정렬

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function solution(files) {
  const answer = [];

  for (let file of files) {
    let [fileName, head, number] = file.match(/^(\D+)([0-9]+)(.*)$/);
    answer.push([fileName, head.toLowerCase(), +number]);
  }

  answer.sort((a, b) => {
    if (a[1] > b[1]) return 1;
    else if (a[1] < b[1]) return -1;
    else if (a[2] > b[2]) return 1;
    else if (a[2] < b[2]) return -1;
  });

  return answer.map((el) => el[0]);
}

정규 표현식 설명

  1. /^ ... $/
    • ^ : 문자열의 시작
    • $ : 문자열의 끝 -> 이 정규식은 문자열 전체가 해당 패턴과 일치해야 함.
  2. (\D+)
    • \D : 숫자가 아닌 문자(숫자가 아닌 모든 문자)를 의미합니다.
    • + : 하나 이상 연속된 문자를 의미합니다. -> 숫자가 아닌 문자로 이루어진 하나 이상의 연속된 문자열
  3. ([0-9]+)
    • [0-9] : 숫자 (0부터 9까지)
    • + : 하나 이상의 숫자 -> 연속된 숫자
  4. (.*)
    • . : 모든 문자
    • * : 0개 이상 -> 남은 모든 문자열을 캡처합니다.

Reference

이 포스트는 아래 게시글의 정보 및 이미지가 사용되었습니다.

  1. 참고 도서 “모던 자바스크립트”
  2. MDN 정규표현식
  3. JavaScript 정규 표현식 문법 총정리

END

This post is licensed under CC BY 4.0 by the author.