JavaScript - 정규식 사용하기
Perl 에서 정규표현식에 대해서 익숙해졌는데, 여태까지 JavaScript 에서는 별로 쓸 일이 없어서 사용 안 하고 있다가 문득 필요한 순간이 오니 한 방 얻어맞은 느낌 마냥 하나도 모르겠어서 부끄러웠다. 그래도 나름 제일 집중적으로 사용하고 있는 언어인데, 이런 기본 기능조차 모르고 있으니… 그래서 이번 글에서는 JavaScript에서 정규식을 사용하는 방법과 그 응용을 정리해보자.
정규식 생성 ¶
JavaScript 에서 정규식을 생성하기 위해서는 RegExp
객체를 이용하면 된다. RegExp
객체는 JavaScript의 내장 객체로써, new
키워드를 이용하여 생성자로 사용 가능하다.
즉 new RegExp('regex-pattern', 'flags')
와 같이 생성자로 사용하면 RegExp
객체를 반환한다. 짧게는 /'regex-pattern'/'flags'
로 표현할 수도 있다. 마치 배열을 new Array('item1', 'item2')
대신 ['item1', 'item2']
로 사용할 수 있는 것과 같다.
'regex-pattern'
라고 써진 부분은 잘 아시다시피 정규식의 패턴을 의미한다. 이 사이트에 가시면 정규식의 패턴에 대해 아주 쉽게 이해할 수 있다.
// 다음 두 줄은 같은 의미이다.
new RegExp('.*describe.*', 'g');
/.*describe.*/g;
정규식 사용 ¶
JavaScript 에서 정규식을 사용할 때에 재미있는 점은, 정규식 패턴을 이용하여 RegExp
객체를 생성한 후, 해당 객체를 이용하여 여러 문자열에 대해 정규식 패턴을 검사할 수 있다는 점이다.
정규식을 사용하는 데에는 크게 다음의 메서드들이 있다.
정규식 사용; RegExp.prototype
¶
RegExp.prototype
에 정의된 메서드에는 exec
와 test
메서드가 있다.
RegExp.prototype.exec(string) ¶
- 파라미터: 문자열
- 반환: 문자열 중 해당
RegExp
객체와 매칭하는 문자열들의 배열
exec
메서드는 파라미터로 문자열을 받으며, 파라미터로 받은 문자열에 해당 RegExp 객체의 패턴이 있는지를 검사한 후, 매칭되는 값들을 배열로 반환한다.
let specFile = load_as_string_from_somewhere('/somewhere/on/disk/some_spec.js');
let testcaseNames = /.*describe\(\'(.+)\'\)/gm.exec(specFile);
개인적으로 이 메서드는 잘 사용하지 않는다.
RegExp.prototype.test(string) ¶
- 파라미터: 문자열
- 반환:
true
/false
test
메서드는 파라미터로 문자열을 받으며, 파라미터로 받은 문자열에 해당하는 RegExp 객체의 패턴이 있는지를 검사한 후, 있으면 true
, 없으면 false
를 반환한다.
let someString = 'I am Korean, and I do love learning something!';
if (/korean/i.test(someString)) {
console.log('당신은 한국인이군요!'); // 출력!
} else {
console.log('Okay, bye...');
}
나는 실제로 JavaScript로 정규식을 작성할 때
test
메서드를 많이 사용한다.
정규식 사용; String.prototype
¶
String.prototype
에 정의된 메서드에는 match
, search
, replace
와 split
메서드가 있다.
String.prototype.match(regex-pattern) ¶
- 파라미터: 정규식 패턴
- 반환: 정규식 패턴에 매칭되는 문자열의 배열
match
메서드는 파라미터로 정규식 패턴을 받아 문자열을 검사한 후, 매칭되는 문자열의 배열을 반환한다.
let specFile = load_as_string_from_somewhere('/somewhere/on/disk/some_spec.js');
let testcaseNames = specFile.match(/.*describe\(\'(.+)\'\)/gm);
위의 exec 예와 동일하다. 상황에 맞는 것을 쓰면 된다.
한글도 된다. 가령…
console.log("정규식 사용하기".match(/사.+/)); // '사용하기'
유니코드 지원 만세!
String.prototype.search(regex-pattern) ¶
- 파라미터: 정규식 패턴
- 반환: 정규식 패턴에 매칭되는 문자열의 인덱스
search
메서드는 파라미터로 정규식 패턴을 받아 문자열을 검사한 후, 첫 번째로 매칭되는 문자열의 인덱스를 반환한다. 만일 매칭되는 문자열이 없으면 -1을 반환한다.
let someString = 'I am Korean, and I do love learning something!';
if (someString.search(/korean/i) !== -1) {
console.log('당신은 한국인이군요!'); // 출력!
} else {
console.log('Okay, bye...');
}
문자열의 인덱스가 필요한 경우에는 그렇게 사용하면 되는데, 사실 아직까진 그런 예를 잘 모르겠다. 가령 다음은 6을 반환하는데,
'Hello World!'.search(/world/i)
내가 만들었던 응용 중에서는 이걸 이용해서 뭔가 할 일이 딱히 없었다.
String.prototype.replace(regex-pattern, replace-tobe-string) ¶
- 파라미터: 정규식 패턴, 교체할 문자열
- 반환: 교체된 문자열
replace
메서드는 2개의 파라미터를 받으며, 정규식 패턴과 교체할 문자열을 받는다. 만약 해당 패턴과 매칭되는 문자열이 있으면 매칭된 문자열을 교체할 문자열로 교체한다.
이 메서드는 immutable method, 즉 원본을 변경시키지 않는 메서드임을 기억해야 한다.
let someString = 'Hello, World! This world is so good! My world, THE WORLD, is not good :(';
console.log(someString.replace(/world/, '세상')); // 'Hello, World! This 세상 is so good! My world, THE WORLD, is not good :('
console.log(someString.replace(/world/i, '세상')); // 'Hello, 세상! This world is so good! My world, THE WORLD, is not good :('
console.log(someString.replace(/world/ig, '세상')); // 'Hello, 세상! This 세상 is so good! My 세상, THE 세상, is not good :('
String.prototype.split(regex-pattern) ¶
- 파라미터: 정규식 패턴
- 반환: 해당 패턴에 매칭된 문자열을 기준으로 쪼개진 문자열의 배열
아마 이 메서드는 많이 써보셨을 것이다. 파라미터로 문자열 뿐 아니라 정규식 패턴을 받을 수도 있다!
let someString = 'Hello, World! This world is so good! My world, THE WORLD, is not good :(';
let splitString = someString.split(/world/i); // ["Hello, ", "! This ", " is so good! My ", ", THE ", ", is not good :("]
MDN 에 보니 ES6에 새로 정의된 Symbol에 관하여 새롭게 추가된 메서드들도 보였다. 이는 나중에 Symbol에 대해 정리하면서 다시 글을 보강해야겠다.