정규표현식(Regular Expression) Part 1

Wonkook Lee·2022년 6월 1일
0
post-thumbnail

Part 1.

Intro

프로그래밍에서 문자열을 다룰 때, 문자열의 일정한 패턴을 표현하는 일종의 형식 언어를 말한다. 정규식이라고도 부르며,보통 regex 혹은 regexp라 많이 쓴다. 링크

특정 포맷의 문자 패턴을 찾아 정규화하거나 새니타이징 할때, 문자열을 찾아 바꿀때, RawHTML 속 원하는 태그를 파싱하거나 마크다운 텍스트를 화면에 렌더링할때도 정규표현식을 유용하게 사용하고 있습니다.

문자열을 처리할때 정규표현식이 꼭 필요했기 때문에 퇴근 후 Udemy 강의를 보며 공부했습니다. 몰랐던 것을 이해하게 되는 순간은 언제나 즐겁습니다. 정규표현식을 공부하며 기록한 메모를 간단히 포스팅합니다.


정규표현식의 역사

  • 정규표현식의 기원은 수학자 스티븐 클레이니(Stephen Keene)가 기술한 정규 언어에서 탄생했습니다.
  • 여러 형태의 정규 표현식들이 Unix 텍스트 처리 유틸리티에서 사용되어 왔습니다.
  • 많은 배리에이션이 있었지만 1992년 POSIX Standard로 표준화되었습니다.
  • 1980년대에 Perl이 등장하여 사용되어져왔고, 이에 착안하여 1997년 필립 하젤(Philip Hazel)이 개발한 PCRE(펄 호환 정규 표현식)은 오늘날의 현대적 정규표현식의 기반이 되었습니다.

자바스크립트에서의 정규표현식

  • 자바스크립트에서 정규표현식은 객체입니다.
  • 정규표현식 객체(RegExp)는 생성자 함수 또는 리터럴 문법으로 만들 수 있습니다.
    • var regex1 = new RegExp('hello'); - 생성자
    • var regex2 = /world/; - 리터럴 문법 ✅
  • 정규표현식 객체의 메서드 또는 String 객체의 메서드로 정규 표현식을 다룰 수 있습니다.

정규표현식 관련 메서드

RegExp 객체 메서드

  • test : 정규식 패턴과 문자열의 일치(Occurance) 여부를 불린으로 반환합니다.
  • exec : 정규식 패턴과의 일치 정보를 배열로 반환합니다.
  • toString : 정규식 문법을 문자열로 변환하여 반환합니다.

String 객체 메서드

  • match : exec 메서드와 같이 일치 정보를 배열로 반환합니다.
  • search : 정규식 패턴과 일치한 문자열의 인덱스를 반환합니다.
  • replace : 정규식 패턴과 일치하는 문자열을 바꿉니다.
  • split : 인자로 전달된 정규식을 기준(델리미터)으로 문자열을 분할하여 배열에 담아 반환합니다.

RegExp.test(string)

정규 표현식 객체가 인자로 전달된 String에 포함되어 있을때 true를 반환합니다.

let regex1 = new RegExp('hello')
let regex2 = /hop/

console.log(regex1.test(txt)) // true
console.log(regex2.test(txt)) // false

RegExp.exec(string)

정규표현식 패턴과 문자열 속 일치하는 곳 문자열의 인덱스, 전달된 문자열을 담은 배열을 반환합니다.

regex1.exec(txt)
regex2.exec(txt)

String.match(RegExp)

test, exec와 달리 String 객체의 메소드입니. 인자로 정규 표현식 객체를 전달합니다. exec과 같이 정보가 담긴 배열을 반환합니다.

txt.match(regex1)
txt.match(regex2)

String.search(RegExp)

문자열에서 전달된 패턴이 일치하는 곳의 인덱스를 반환합니다.

txt.search(regex) // 41

String.replace(RegExp, String)

전달된 패턴을 찾아 두번째 인자로 전달된 문자로 바꿔줍니다.
원본 문자열을 변조하지 않고 새로운 바뀐 문자열을 반환합니다.

txt.replace(/hello/g, 'hi') // hello를 hi로 바꿉니다.
// Programming courses always starts with a hi world example.

String.split(String)

전달된 문자(Delimitter)를 기준으로 문자열을 나누어 배열로 반환합니다.

helloworld 단어로 문장을 나눴을때

let txt = 'Programming courses always starts with a hello world example.'

let regex1 = /hello/
let regex2 = /world/

// split
// Split is the way it does that is you specify what character or characters you want to perform the split on.
console.log(txt.split(regex1))
console.log(txt.split(regex2))

공백(\s)으로 문자열을 나눴을때

// splits a string into words with space
let regex3 = /\s/ // space key
console.log(txt.split(regex3).map(ele => ele.trim()))


메타캐릭터(Metacharacters) 이해하기

let re = /hello/;
here help hello
🙅‍♂️         🙅🏻‍♀️        🙆‍♂️
정규표현식은 패턴이 일치할때까지 문자열을 리와인드하며 완전히 일치하는 문자를 찾습니다. 따라서 문자열 그 자체로 찾는것은 비효율적입니다. 일일히 찾는 비효율성을 개선하기 위해 메타캐릭터를 사용합니다.

^$.*+?=!:|\/()[]{}

와일드카드 (.)

와일드카드(Dot)는 개행을 제외하고 모든 글자와 일치합니다.

h와 t 사이 공백이나 탭, 어떤 문자가 와도 일치한다. 하나의 와일드카드는 하나의 문자에 상응합니다. (점 한개, 문자 하나)

이스케이핑 (\)

  • 모든 문자와 숫자는 그 문자 그대로 정규표현식에서 매칭됩니다.
  • 특정한 비-알파벳 문자들은 역슬래시(\)로 시작하는 이스케이프 문자열을 사용해야 문자로 인식됩니다.
  • 구두점 문자(?,!,.,등)을 일반 문자로 취급하려면 반드시 \를 문자 앞에 붙여야합니다.

Escaped characters
\. \* \
escaped special characters
\t \n \r
tab, linefeed, carriage return
\u00A9
unicode escaped ©

d와 백슬래시를 한 세트로 선택하려면 특수 문자를 일반 문자로 취급하기 위해 백슬래시 앞에 백슬래시를 한 번 더 붙여줍니다.

컨트롤캐릭터

탭, 개행에 대응하는 메타캐릭터도 있습니다.

\t = tab
\v = vertical tab
\n = newline
\r = carriage return

탭 일치

개행 일치

CR(\r), LF(\n)은 무슨 차이인가요?

일단 \r이라는 탈출 문자(Escape Character)는 Carriage Return(CR)이란 의미를 가지며 \nLine Feed(LF)란 의미를 가지며 일반적으로 New Line이라고 읽습니다.
CR(\r), LF(\n)이란 무엇인가? : 네이버 블로그

  • CR은 Carriage Return, LF는 Line Feed
  • typewriter의 유물, teletype에서 사용하기 위한 제어 코드
  • unix-like는 LF, windows는 CRLF

그래서 Unix-like OS에서는 한 줄 내림을 LF만 가지고 표시한다.
재미있는 점은 Windows OS에서는 한 줄 내림을 전통적인 방식의 CRLF를 쓴다는 점이다.
이러한 이유로 한 줄 내림을 CRLF로만 인식하는 notepad(메모장)의 경우 unix-like os에서 작성한 문서를 열었을 때 모두 한 줄로 나오고 깨져 보이는 현상을 겪게 된다.


캐릭터 셋(Character Sets)

정규표현식으로 문자 집합을 찾아 매칭할 수 있습니다.
이를 캐릭터셋이라고 합니다.

Sets [ … ]

브라켓으로 감싼 캐릭터 그룹 중 하나와 같다면 일치합니다.

gray or grey

  • let re = /gr.y/
    이렇게 하면 gray, grey가 아닌 groy가 선택될 수도 있습니다.

  • let re = /gr[ae]y/
    브라켓으로 감싸면 a 또는 e가 중간 자리에 있는 단어와 매칭됩니다.

연속(체이닝)으로 사용할 수 있습니다.

/[rh][abcde][ i]/g
r 또는 h + a/b/c/d/e 중 하나 + 공백 또는 i

캐릭터 셋으로 범위 정하기 (Specifying a Range)

Range /[1-4]/

Set과 함께 사용되어 범위를 설정할 수 있으며 하이픈은 메타캐릭터로 작용합니다.

  • /[1-9]/ = 1과 9 사이의 알파벳
  • /[a-e]/ = a와 e 사이의 알파벳
  • /[1-6][1-6]/ = 1과 6사이의 숫자 + 1과 6사이의 숫자
  • /[0-9a-zA-Z ~,]/ = 0부터 9 사이의 숫자 || a부터 z 사이의 소문자 || A부터 Z 사이의 대문자 || ~ || , || 공백
  • /[12\-5]/ = 1 또는 2 또는 하이픈 또는 5
  • /[12-5]/ = 1 또는 2부터 5 사이의 숫자

헷갈리지 마세요! 숫자로 범위를 정할때 오직 한자리 수만 유효합니다.

10부터 20까지의 숫자가 아니라 1 또는 0부터 2 사이의 숫자 또는 0

특정 문자 제외하기 (Excluding)

Negative Sets

캐릭터 셋 내의 문자를 제외한 문자를 찾을때 캐럿^을 앞에 붙여줍니다.

영어를 제외하고 한글과 숫자를 선택할 수 있고

영어를 선택하고 네거티브 셋으로 반전시킬수도 있습니다.

캐릭터 셋의 단축형 (Shorthands)

Positives

\d

[0-9] 숫자 (Digits)를 포함합니다.

\w

[a-zA-Z0-9_] 알파벳 문자와 숫자 + 언더스코어를 포함합니다.

\s

[\t\r\n] 공백 문자열 (White Spaces)을 포함합니다.

Negatives

\D

[0-9] 숫자 (Digits)를 제외합니다.

\W

[^a-zA-Z0-9_] 대/소문자 알파벳, 숫자, 언더스코어를 제외합니다.

\S

[^\t\r\n] 공백 문자열을 제외합니다.



🙏🏻

Wonkook Lee
Frontend Developer
LinkedIn

profile
© 가치 지향 프론트엔드 개발자

0개의 댓글