JavaScript RegExp
Short book about the Regular Expressions
1. RegExp ๐ฉโ๐ป
1. Features of the RegExp
์ ๊ทํํ์์ ์ฃผ์ ๊ธฐ๋ฅ์ด๋ค.
- ๋ฌธ์ ๊ฒ์(Search)
- ๋ฌธ์ ์ถ์ถ(Extract)
- ๋ฌธ์ ๋์น(Replace)
์ฌ์ค ํ์ฌ์์ ์ผํ๋ฉฐ ์ ๊ทํํ์์ ์ผ๋ ๊ฑด ๊ฑฐ์ Validation Check ๋ง๊ณค ์์๋ ๊ฒ ๊ฐ๊ธด ํ๋ฐ ๋งค๋ฒ https://regexr.com ์ ์์กดํด์ ์ฌ์ฉํ์๋ค. ์ญ์ ๊ณ์ ์ฌ์ฉํ๋ ๊ฒ๋ ์ข์ง๋ง ํ ๋ฒ ์ ๋ฆฌํด์ ๊ธ๋ก ๊ธฐ๋กํ๋ ๊ฒ ๋งํผ ๋จธ๋ฆฟ์๋ ์ ๋ฆฌ๋๊ณ , ๋์ค์ ๋ค์ ์ฐพ์๋ณด๊ธฐ ์ข์ ๊ฒ์ ์๋ ๊ฒ ๊ฐ์ ๊ธ๋ก ์์ฑํด๋ณด๊ณ ์ํ๋ค.
์ด ๊ธ์์ ์ฌ์ฉํ ๋ฌธ์์ด์ ๋ค์๊ณผ ๊ฐ๋ค.
const str = `
010-1234-5678
thesecon@gmail.com
Hello world!
https://www.omdbapi.com/?apikey=7035c60c&s=frozen
The quick brown fox jumps over the lazy dog.
hello@naver.com
http://localhost:1234
๋ํด๋ฌผ๊ณผ ๋ฐฑ๋์ฐ์ด ๋ง๋ฅด๊ณ ๋ณ๋๋ก
abbcccddddeeeee
`;
2. Features of the RegExp
__ 1) Constructors__
// new RegExp('ํํ', '์ต์
')
new RegExp('[a-z]', 'gi')
__ 2) Literals__
// /ํํ/์ต์
/[a-z]/gi
์์ฑ์ ๋ฐฉ์์ผ๋ก๋ง ์ ํจํ๊ฒ ์ฌ์ฉํ ์ ์๋ ํจํด์ด ์กด์ฌํ ๋๋ฅผ ์ ์ธํ๋ฉด ์ผ๋ฐ์ ์ผ๋ก ๋ฆฌํฐ๋ด ๋ฐฉ์์ ์ฌ์ฉํ๋ค.
3. Methods
์ฃผ๋ก ์ฌ์ฉํ๋ ๋ฉ์๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
regexp.test(string:) -> boolean
: ๋ฌธ์ ๊ฒ์(Search)string.match(regexp:) -> string[]
: ๋ฌธ์ ์ถ์ถ(Extract) - ์ผ์นํ๋ ๋ฌธ์์ ๋ฐฐ์ด์ ๋ฐํstring.replace(regexp:,replacement:)
: ๋ฌธ์ ๋์น(Replace)
console.log(regexp.test(str)); // true
console.log(str.match(regexp)); // ['fox']
console.log(str.replace(regexp, 'cat'));
test
๋ ์ ๊ท์์ ๋ฉ์๋๊ณ ,match
์replace
๋ string ์ ๋ฉ์๋๋ค.
4. Options(=Flags)
g
: ๋ชจ๋ ๋ฌธ์ ์ผ์น(Global)i
: ๋์๋ฌธ์ ๋ฌด์(Ignore Case)m
: Multi Line, ์ค๋ฐ๊ฟ์ ๊ฐ๊ฐ์ ๋ฌธ์์ด๋ก ์ธ์
console.log(str.match(/the/));
[
0: 'the',
index: 15,
input: '\n010-1234-5678\nthesecon@gmail.com\nHello world!\nhttโฆocalhost:1234\n๋ํด๋ฌผ๊ณผ ๋ฐฑ๋์ฐ์ด ๋ง๋ฅด๊ณ ๋ณ๋๋ก\nabbcccddddeeeee\n',
groups: undefined
]
๊ฐ์ฅ ์์ ๋์ค๋ the
๋ฅผ ํ๋๋ง ์ฐพ๋๋ค.
console.log(str.match(/the/g)); // ['the', 'the']
console.log(str.match(/the/gi)); // ['the', 'The', 'the']
the
๋ฅผ ์ฌ๋ฌ ๊ฐ ์ฐพ๊ณ , the
๋ฅผ ๋์๋ฌธ์ ๊ตฌ๋ถ ์์ด ์ฌ๋ฌ ๊ฐ ์ฐพ๋๋ค.
console.log(str.match(/\.$/gi)); // null
.
์ ์ ๊ท์์์ ๊ธฐ๋ฅ์ ๊ฐ๊ณ ์์ด ๋ฌธ์์ด๋ก ์ฌ์ฉํ๊ธฐ ์ํด Escape Character \
๋ฅผ ์์ ๋ถ์ฌ์ฃผ์๋ค. $
๋ ๋ฌธ์ฅ์ด ๋๋จ์ ์๋ฏธํ๋ค.
console.log(str.match(/\.$/gim)); // ['.']
m
์ด ํฌํจ๋์ ๋ฌธ์์ด ์ ์ฒด๊ฐ ์๋ ๋ผ์ธ ๋จ์๋ก ๊ฒ์ฌํด .
๋ก ๋๋๋ ๋ฌธ์์ด์ ์ฐพ์ ์ถ์ถํ๋ค.
2. Patterns ๐ฉโ๐ป
const str = `
010-1234-5678
thesecon@gmail.com
Hello world!
https://www.omdbapi.com/?apikey=7035c60c&s=frozen
The quick brown fox jumps over the lazy dog.
hello@naver.com
http://localhost:1234
๋ํด๋ฌผ๊ณผ ๋ฐฑ๋์ฐ์ด ๋ง๋ฅด๊ณ ๋ณ๋๋ก
abbcccddddeeeee
`;
๋ฅผ ์ด์ด์ ์ฌ์ฉํ๋ค.
1. Basic Patterns
^ab
: Line ์์์ ์๋ ab ์ ์ผ์น.ab$
: Line ๋์ ์๋ ab ์ ์ผ์น..
: ์์์ ํ ๋ฌธ์์ ์ผ์น.a|b
: a ๋๋ b ์ ์ผ์น.ab?
: ? ๋ฐ๋ก ์ง์ ์ ๋ฌธ์๋ฅผ optional ๋ก ์ผ์น.
console.log(str.match(/^h.../gm)); // ['http', 'hell', 'http']
console.log(str.match(/\.com$/gm)); // ['.com', '.com']
console.log(str.match(/...\.com$/gm)); // ['ail.com', 'ver.com']
console.log(str.match(/fox|dog/g)); // ['fox', 'dog']
console.log(str.match(/https?/g)); // ['https', 'http']
/https?/g
๋ /https|http/g
์ ๊ฐ๋ค. ๋จ, /http|https/g
๋ ์๋ชป๋ ํํ์์์ ์ ์ํ๋ค. ์ ํ ์กฐ๊ฑด์ ์ผ์น ์ฌ๋ถ๋ฅผ ๋จผ์
๊ฒ์ฌํ๊ธฐ ๋๋ฌธ์ http
๋ง ์ฐพ๊ณ ์ผ์น๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ https
๊น์ง ๊ฒ์ฌ๋ฅผ ํ์ง ์๋๋ค. ๋๋ฌํ ์ ์๋ ์กฐ๊ฑด์ ํด๋นํ๋ค.
console.log(str.match(/https?/g)); // ['https', 'http']
console.log(str.match(/https|http/g)); // ['https', 'http']
console.log(str.match(/http|https/g)); // ['http', 'http']
2. Range Patterns
๋ฒ์ ํจํด์ [ ]
๋ฅผ ์ฌ์ฉํ๋ค.
[abe]
: a ๋๋ b ๋๋ e ์ ์ผ์น.[a-z]
: a ๋ถํฐ z ๊น์ง ์ผ์น.[A-Z]
: A ๋ถํฐ Z ๊น์ง ์ผ์น.[0-9]
: 0 ๋ถํฐ 9 ๊น์ง ์ผ์น.[๊ฐ-ํฃ]
: ๊ฐ ๋ถํฐ ํฃ ๊น์ง ์ผ์น.
console.log(str.match(/[fgj]/g)); // ['g', 'f', 'f', 'j', 'g']
[ ]
์์ -
๋ฅผ ํฌํจํ์ง ์์ผ๋ฉด ๊ฐ ๋ฌธ์๋ฅผ |
๋ก ์ผ์น ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ๋ ๊ฒ๊ณผ ๊ฐ๋ค. ๋ฐ๋ผ์ [fgj]
๋ f|g|j
์ ๊ฐ๋ค.
console.log(str.match(/[0-9]/g)); // ['0', '1', '0', '1', '2', '3', '4', '5', '6', '7',
// '8', '7', '0', '3', '5', '6', '0', '1', '2', '3', '4']
console.log(str.match(/[๊ฐ-ํฃ]/g)); // ['๋', 'ํด', '๋ฌผ', '๊ณผ', '๋ฐฑ', '๋', '์ฐ', '์ด',
// '๋ง', '๋ฅด', '๊ณ ', '๋ณ', '๋', '๋ก']
console.log(str.match(/[๊ฐ-ํฃ]+/g)); // ['๋ํด๋ฌผ๊ณผ', '๋ฐฑ๋์ฐ์ด', '๋ง๋ฅด๊ณ ', '๋ณ๋๋ก']
+
๊ธฐํธ๋ ๋ฐ๋ก ๋ค์ Repeat Patterns ์์ ํ์ธํ ์ ์๋ค.
3. Repeat Patterns
๋ฐ๋ณต ํจํด์ { }
๋๋ ํน์ํ ๊ธฐ๋ฅ์ ๊ฐ๋ +
๋ฅผ ์ฌ์ฉํ๋ค.
{m}
: mํ ์ฐ์ ์ผ์น{m,}
: mํ ์ด์ ์ฐ์ ์ผ์น{m,n}
: mํ ์ด์ nํ ์ดํ ์ฐ์ ์ผ์น+
: 1ํ ์ด์ ์ฐ์ ์ผ์น
console.log(str.match(/\d{3}/g)); // ['010', '123', '567', '703', '123']
console.log(str.match(/\d{3,}/g)); // ['010', '1234', '5678', '7035', '1234']
console.log(str.match(/\d{2,4}/g)); // ['010', '1234', '5678', '7035', '60', '1234']
console.log(str.match(/\d+/g)); // ['010', '1234', '5678', '7035', '60', '1234']
\d
๋ ๋ฐ๋ก ๋ค์ Escape Patterns ์์ ํ์ธํ ์ ์๋ค.
console.log(str.match(/e{3}/g)); // ['eee']
console.log(str.match(/[a-z]+/g)); // ['thesecon', 'gmail', 'com', 'ello', 'world', 'https',
// 'www', 'omdbapi', 'com', 'apikey', 'c', 'c', 's', 'frozen',
// 'he', 'quick', 'brown', 'fox', 'jumps', 'over', 'the',
// 'lazy', 'dog', 'hello', 'naver', 'com', 'http', 'localhost',
// 'abbcccddddeeeee']
+
๋ {1,}
์ ๊ฐ๋ค.
์ด๋ฅผ ์์ฉํ๋ฉด ์์์ ํ๋ ์ด์์ ๋ชจ๋ ๋ฌธ์ ์ผ์น๋ .{1,}
๋๋ .+
๊ฐ ๋๊ณ , 0๊ฐ ์ด์์ ๋ชจ๋ ๋ฌธ์ ์ผ์น๋ .{0,}
๋๋ .*
๊ฐ
๋๋ค.
4. Escape Patterns
\w
: 63๊ฐ ๋ฌธ์(๋๋ฌธ์(26) + ์๋ฌธ์(26) + ์ซ์(10) + _(1) ์ด 63๊ฐ)์ ์ผ์น,[a-zA-Z0-9_]
์ ๊ฐ๋ค.\b
: 63๊ฐ ๋ฌธ์์ ์ผ์นํ๋ ์๋ ๋ฌธ์ ๊ฒฝ๊ณ(Boundary).\d
: ์ซ์(Digit)์ ์ผ์น,[0-9]
์ ๊ฐ๋ค.\s
: ๊ณต๋ฐฑ(Space, Tab, Newline ๋ฑ)๊ณผ ์ผ์น.
console.log(str.match(/[0-9]/g)); // ['0', '1', '0', '1', '2', '3', '4', '5', '6', '7',
// '8', '7', '0', '3', '5', '6', '0', '1', '2', '3', '4']
console.log(str.match(/\d/g)); // ['0', '1', '0', '1', '2', '3', '4', '5', '6', '7',
// '8', '7', '0', '3', '5', '6', '0', '1', '2', '3', '4']
console.log(str.match(/\w+/g)); // ['010', '1234', '5678', 'thesecon', 'gmail', 'com',
// 'Hello', 'world', 'https', 'www', 'omdbapi', 'com',
// 'apikey', '7035c60c', 's', 'frozen', 'The', 'quick',
// 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog',
// 'hello', 'naver', 'com', 'http', 'localhost', '1234',
// 'abbcccddddeeeee']
_
๋ฅผ ํฌํจํด ๋ชจ๋ ์๋ฌธ ๋์๋ฌธ์์ ์ซ์๋ฅผ ์ถ์ถํ๋ค.
console.log(str.match(/\s/g)); // ['\n', '\n', '\n', ' ', '\n', '\n', ' ', ' ', ' ', ' ',
// ' ', ' ', ' ', ' ', '\n', '\n', ' ', '\n', ' ', ' ', ' ',
// '\n', '\n']
const str = `
a111a
#222a
a333#
#444#
010-1234-5678
`;
console.log(str.match(/[0-9]+/g)); // ['111', '222', '333', '444', '010', '1234', '5678']
console.log(str.match(/\b[0-9]+/g)); // ['222', '444', '010', '1234', '5678']
console.log(str.match(/[0-9]+\b/g)); // ['333', '444', '010', '1234', '5678']
console.log(str.match(/\b[0-9]+\b/g)); // ['444', '010', '1234', '5678']
\b
๋ ๋จ๋
์ผ๋ก ์ฌ์ฉ๋์ง ์๊ณ ์์ ๊ฐ์ด ๋ค๋ฅธ ํจํด๊ณผ ๊ฒฐํฉํด Boundary
๋ฅผ ๊ฒ์ฌํ๊ธฐ ์ํ ์ฉ๋๋ก ์ฌ์ฉํ๋ค.
- ์ฒซ ๋ฒ์งธ ๋งค์นญ์ ๋ชจ๋ ์ฐ์๋ ์ซ์๋ฅผ ์ถ์ถํ๋ค.
- ๋ ๋ฒ์งธ ๋ฏธ์นญ์
word ๊ฐ ์๋ ๊ฒ
๋ค์์ฐ์๋ ์ซ์ ์กฐํจ
์ ์ฐพ๊ธฐ ๋๋ฌธ์ ์์ ๋ฌธ์ a ๊ฐ ๋ถ์ ์ซ์ 111๊ณผ 333์ ์ ์ธ๋์๋ค. - ์ธ ๋ฒ์งธ ๋งค์นญ์ ๋ฐ๋๋ก ๋ค์
word ๊ฐ ์๋ ๊ฒ
์ ์ฐพ์ผ๋ฏ๋ก, ๋ค์ ๋ฌธ์ a ๊ฐ ๋ญ์ ์ซ์ 222์ 444๋ ์ ์ธ๋์๋ค. - ๋ค ๋ฒ์งธ ๋งค์นญ์ ์๋ค๊ฐ ๋ชจ๋
word ๊ฐ ์๋ ๊ฒ
์ ์ฐพ์ผ๋ฏ๋ก, ์ซ์ 444, 010, 1234, 5678 ๋ง ์ถ์ถํ๋ค.
5. Group Patterns
(?:)
: ๊ทธ๋ฃน ์ผ์น(?=)
: ๊ทธ๋ฃน ์์ชฝ ํ์(Lookahead), ๋ท์ชฝ์ Boundary ๋ฅผ ์ค์ ํด ์์ชฝ ์ผ์น๋ฅผ ํ์(?<=)
: ๊ทธ๋ฃน ๋ท์ชฝ ํ์(Lookbehind), ์์ชฝ์ Boundary ๋ฅผ ์ค์ ํด ๋ท์ชฝ ์ผ์น๋ฅผ ํ์
1 ) (?:)
: ๊ทธ๋ฃน ์ผ์น
http
๋๋ https
๋ฅผ ํฌํจํด ๋๋ฉ์ธ์ ์ถ์ถํ๊ณ ์ถ๋ค๊ณ ํด๋ณด์.
const str = `
https://www.omdbapi.com?apikey=7035c60c&s=frozen
http://localhost:1234
https://www.amazon.com/gp/bestsellers/?ref_=nav_em_cs_bestsellers_0_1_1_2
`;
console.log(str.match(/https?:\/\/\w+\.?/g));
// ['https://www.', 'http://localhost', 'https://www.']
์ด์ \w+\.?
์ด ๋ถ๋ถ์ ๋ฐ๋ณตํ ๊ฒ์ด๋ค.
console.log(str.match(/https?:\/\/\w+\.?\w+\.?/g));
// ['https://www.omdbapi.', 'http://localhost', 'https://www.amazon.']
console.log(str.match(/https?:\/\/\w+\.?\w+\.?\w+\.?/g));
// ['https://www.omdbapi.com', 'http://localhost', 'https://www.amazon.com']
๋๋ฉ์ธ ๋ง์ง๋ง์ /
๋ก ๋๋ ๊ฒฝ์ฐ ์ด๊ฒ๋ ํฌํจ์ํค๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํ๊ณ \/?
๋ฅผ ๋ง์ง๋ง์ ์ถ๊ฐํด๋ณด์.
console.log(str.match(/https?:\/\/\w+\.?\w+\.?\w+\.?\/?/g));
// ['https://www.omdbapi.com', 'http://localhost', 'https://www.amazon.com/']
์ ํจํด์ ๋ฌธ์ ๋ ๋์ผ ํจํด์ด ๋ฐ๋ณต๋๋ ๋ฐ ๊ณ์ํด์ ํ๋์ฝ๋ฉ ํ๋ค๋ ๊ฒ์ด๊ณ , ๋ฐ๋ณต๋๋ ํจํด์ ํ์๊ฐ ๊ณ ์ ์ด ์๋๋ผ๋ ๊ฒ์ด๋ค.
console.log(str.match(/https?:\/\/(?:\w+\.?)+\/?/g));
// ['https://www.omdbapi.com', 'http://localhost', 'https://www.amazon.com/']
๋ฐ๋ณต๋๋ ํจํด \w+\.?
์ (?:\w+\.?)+
๋ก ๊ทธ๋ฃนํ ํ๊ณ , ๋ค์ \/?
๋ฅผ ์ถ๊ฐํด์ฃผ๋ฉด ์ด๋ค ๊ฒฝ์ฐ์๋ ์๋์ด ๊ฐ๋ฅํ๋ค.
2 ) (?=)
: ๊ทธ๋ฃน ์์ชฝ ์ผ์น(Lookahead)
\b
์ ๋ง์ฐฌ๊ฐ์ง๋ก Boundary
๊ฐ๋
์ผ๋ก ์ฌ์ฉ๋๋ค.
const str = `
์๋ชฌ๋์ฐ์
์๋ชฌ๋๋นต
์๋ชฌ๋์๋ฌ๋
๋ฐ๋๋์ฐ์
๋ฐ๋๋๋นต
๊ณ ๊ตฌ๋ง์ฐ์
๊ณ ๊ตฌ๋ง๋นต
๊ณ ๊ตฌ๋งํ๊น
๊ณ ๊ตฌ๋งํผ์
`;
console.log(str.match(/.+(?:์ฐ์ )/g)); // ['์๋ชฌ๋์ฐ์ ', '๋ฐ๋๋์ฐ์ ', '๊ณ ๊ตฌ๋ง์ฐ์ ']
console.log(str.match(/.+(?=์ฐ์ )/g)); // ['์๋ชฌ๋', '๋ฐ๋๋', '๊ณ ๊ตฌ๋ง']
(?:)
: ๊ทธ๋ฃน ์ผ์น๋ ์ฐ์
๋ฅผ ํฌํจํด โ์๋ชฌ๋์ฐ์ โ, โ๋ฐ๋๋์ฐ์ โ, โ๊ณ ๊ตฌ๋ง์ฐ์ โ๋ฅผ ์ถ์ถํ์ง๋ง,
(?=)
: ๊ทธ๋ฃน ์์ชฝ ํ์(Lookahead)์ ์ฐ์
๋ฅผ ๋ท์ชฝ Boundary ๋ก ์ค์ ํด ์ฐ์
๋ฅผ ์ ์ธํ ์์ชฝ์ ์ผ์น ๋ฌธ์์ด โ์๋ชฌ๋โ, โ๋ฐ๋๋โ,
โ๊ณ ๊ตฌ๋งโ๋ง ์ถ์ถํ๋ค.
3 ) (?<=)
: ๊ทธ๋ฃน ๋ค์ชฝ ์ผ์น(Lookbehind)
console.log(str.match(/(?:๊ณ ๊ตฌ๋ง).+/g)); // ['๊ณ ๊ตฌ๋ง์ฐ์ ', '๊ณ ๊ตฌ๋ง๋นต', '๊ณ ๊ตฌ๋งํ๊น', '๊ณ ๊ตฌ๋งํผ์']
console.log(str.match(/(?<=๊ณ ๊ตฌ๋ง).+/g)); // ['์ฐ์ ', '๋นต', 'ํ๊น', 'ํผ์']
(?:)
: ๊ทธ๋ฃน ์ผ์น๋ ๊ณ ๊ตฌ๋ง
๋ฅผ ํฌํจํด โ๊ณ ๊ตฌ๋ง์ฐ์ โ, โ๊ณ ๊ตฌ๋ง๋นตโ, โ๊ณ ๊ตฌ๋งํ๊นโ, โ๊ณ ๊ตฌ๋งํผ์โ๋ฅผ ์ถ์ถํ์ง๋ง,
(?<=)
: ๊ทธ๋ฃน ๋ท์ชฝ ํ์(Lookbehind)์ ๊ณ ๊ตฌ๋ง
๋ฅผ ์์ชฝ Boundary ๋ก ์ค์ ํด ๊ณ ๊ตฌ๋ง
๋ฅผ ์ ์ธํ ๋ท์ชฝ์ ์ผ์น ๋ฌธ์์ด โ์ฐ์ โ, โ๋นตโ,
โํ๊นโ, โํผ์โ๋ง ์ถ์ถํ๋ค.
Reference
- ๋ฐ์์ , โํ๋ก ํธ์๋ ์น ๊ฐ๋ฐ์ ๋ชจ๋ ๊ฒ ์ด๊ฒฉ์ฐจ ํจํค์ง Online.โ fastcampus.co.kr. last modified unknown, Fast Campus.