[JS] #10 RegExp 오브젝트

simoniful·2021년 4월 29일
0

ES6 JS - Basic

목록 보기
10/18
post-thumbnail
post-custom-banner

정규표현식

개발을 하며 특정 문자를 바꾸거나 문자열이 유효성을 검사하거나, 개발자가 제한한 검사기준을 통과했는지 등을 검사, 평가 교환할 때 정규 표현식을 사용하면 편리합니다.

정규 표현식(regular expression)이란 특정한 규칙을 가진 문자열의 집합을 표현하는데 사용하는 형식언어로써 패턴을 사용해 문자열의 검색과 치환을 돕습니다.

RegExp 오브젝트란 JS에서 지원하는 오브젝트로써 패턴을 사용해 텍스트를 판별할 때 사용합니다. 이 오브젝트는 리터럴 표기법과 생성자로써 생성할 수 있는데,

/ab+c/i
new RegExp(/ab+c/, 'i');   // 리터럴
new RegExp('ab+c', 'i');   // 생성자
  • 리터럴 표기법의 매개변수는 두 빗금으로 감싸야 하며 따옴표를 사용하지 않습니다.
  • 생성자 함수의 매개변수는 빗금으로 감싸지 않으나 따옴표를 사용합니다.

lastIndex

lastIndex는 RegExp 오브젝트의 내부 프로퍼티 중 하나로써 매치 시작 위치를 설정합니다. 기본값은 0으로 플래그에 따라서 사용 여부가 결정됩니다.

기본적인 사용 형태

const value = "ABC";
const obj = new RegExp("A", "g");
console.log(obj.test(value));
const reg = /A/g;
console.log(reg.test(value));
// true
// true
  1. const obj = new RegExp("A", "g");
    ⇒ RegExp 인스턴스를 생성하며 A로 매치대상에 매치합니다. 두 번째 파라미터인 "g"는 글로벌 플래그로써 모두 매치한다는 의미입니다.
  2. console.log(obj.test(value));
    ⇒ obj에 설정된 A를 ABC에 매치하여 A가 있는지 검색하는데 있기 때문에 true를 반환합니다.
  3. const reg = /A/g;
    ⇒ 정규 표현식 리터럴을 사용한 형태로 new 연산자를 사용하진 않았지만 1번과 동일합니다.

g플래그

const value = "ABABA", obj = /B/g;
console.log(obj.test(value) +": "+obj.lastIndex);
console.log(obj.test(value) +": "+obj.lastIndex);
console.log(obj.test(value) +": "+obj.lastIndex);
// true: 2
// true: 4
// false: 0
  1. obj.test(value)
    ⇒ B가 ABABA에 있으므로 매치되어 true를 반환합니다.
  2. obj.lastIndex
    ⇒ lastIndex값으로 2가 출력됩니다. B가 매치된 인덱스는 1인데 2가 출력된 이유는 1은 매치된 인덱스이고 lastIndex는 다음에 매치를 시작할 인덱스를 저장하기 때문에 +1하여 2가 설정됩니다.
  3. obj.test(value)
    ⇒ lastIndex값이 2이기 때문에 대상 문자열(ABABA)의 2번째 인덱스부터 B를 매치합니다.
  4. obj.lastIndex
    ⇒ 2번째 인덱스부터 B를 매치한 결과 3번째 인덱스에 B가 매치되기 때문에 +1한 4가 lastIndex에 설정되어 출력됩니다.
  5. obj.test(value)
    ⇒ 4번째 인덱스부터 B를 매치하는데 더이상 매치가 되지않기에 false가 출력됩니다.
  6. obj.lastIndex
    ⇒ 매치가 되지 않을 경우 lastIndex값은 0이 됩니다.(초기상태)
  • g플래그를 사용하지 않을 경우
    lastIndex 프로퍼티 값은 변경되지 않으며 개발자가 따로 값을 지정해줘도 항시 0번 인덱스부터 매치를 시작합니다.
    const value = "ABABA", obj = /B/;
    console.log(obj.test(value) +": "+obj.lastIndex);
    obj.lastIndex = 2;
    console.log(obj.test(value) +": "+obj.lastIndex);
    console.log(obj.test(value) +": "+obj.lastIndex);
    // true: 0
    // true: 2
    // true: 2

y플래그

RegExp 오브젝트에서는 플래그를 어떻게 설정하느냐에 따라 같은 문자열과 같은 정규식을 쓰더라도 다른 결과값을 볼 수 있습니다.

g플래그를 사용하면 lastIndex가 업데이트되며 전체 순회를하면서 문자열 검색&치환을 할 수 있습니다. 플래그가 없을경우 매번 처음부터 매치를 합니다.

y플래그는 또한, lastIndex를 사용하지만, g플래그와는 다릅니다. g플래그가 lastIndex부터 매치를 한다면, y플래그는 lastIndex위치를 매치합니다.

즉, g플래그가 lastIndex의 위치부터 끝까지 문자열을 하나씩 매치를 한 다음 매치가 없을 경우 lastIndex를 0으로 하고 매치가 있을 경우 해당 위치 +1을 lastIndex로 한다면

y플래그는 lastIndex위치에 매치를 하고 매치가 될 경우에만 +1을 하고 아니면 그 뒤를 순회하는게 아닌 바로 lastIndex에 0을 설정합니다.

const value = "AABBA", obj = /A/y
console.log(obj.test(value) + ": "+ obj.lastIndex);
console.log(obj.test(value) + ": "+ obj.lastIndex);
console.log(obj.test(value) + ": "+ obj.lastIndex);
// true: 1
// true: 2
// false: 0
  1. console.log("1-"+obj.test(value) + ": "+ obj.lastIndex)
    ⇒ default lastIndex는 0이기에 AABBA의 첫 번째 인덱스에 위치한 값인 A를 obj에 매치해본결과 true가 반환되고 lastIndex는 0 +1이 되어 1이 됩니다.
  2. console.log("2-"+obj.test(value) + ": "+ obj.lastIndex)
    ⇒ lastIndex는 이제 1이고 AABBA의 1번째 인덱스에 위치한 문자는 A이고 obj와 매치한 결과 true가 반환됩니다. 그래서 lastIndex는 1 +1이 되어 2가 됩니다.
  3. console.log("3-"+obj.test(value) + ": "+ obj.lastIndex)
    ⇒ lastIndex가 2이기에 문자열의 2번째 위치부터 매치를 하는데 문자는 B이기 때문에 매치한 결과는 false입니다. 그래서 false가 반환되며 lastIndex는 0이 됩니다.

문자열 value를 보면 마지막 문자가 A입니다. 하지만, 중간의 B를 만나 매치 결과가 false가 되면 lastIndex는 0이되기 때문에 마지막 문자를 매치할 수 없습니다. 이를 통해 연속된 문자 패턴을 검증하는 경우에 y플래그는 유용하게 사용됩니다.

  • lastIndex값 임의로 지정
    y플래그를 사용하면 프로퍼티 중 sticky 프로퍼티가 true가되기에 조건문을 통해 stickey를 확인 후 y플래그인 것이 확인되면 lastIndex를 임의로 변경해 매치를 시도할 수도 있습니다.
    const value = "AABBA", obj = /A/y
    if(obj.sticky)
      obj.lastIndex = 4;
    console.log(obj.test(value) + ": "+ obj.lastIndex);
    // true: 5

u플래그, s플래그

u플래그

u플래그는 정규 표현식의 패턴을 유니코드의 코드 포인트로 변환하여 매치합니다. 더하여 내부 프로퍼티 중 unicode 프로퍼티가 true로 설정됩니다. 만일 u플래그를 사용하지 않는다면 코드포인트를 변환하지 않고 문자로 매치합니다.

const obj = new RegExp("\u{31}\u{32}", "u");
const obj2 = new RegExp(String.raw `\u{31}\u{32}`)
console.log(obj.test("12"));           //true
console.log(obj.unicode);              //true
console.log(obj2.test("12"));          //false
console.log(obj2.unicode);             //false
console.log(/\u{1f418}/u.test("🐘"));  //true
console.log(/\u{1f418}/.test("🐘"));   //false

s플래그

✔ ES2018 부터 지원

기존에 정규 표현식에서 dot(점.)은 모든 문자를 매치하지만 줄 바꿈 문자는 매치하지 않았습니다. 하지만 ES2018부터 지원되는 S플래그를 사용하면 줄 바꿈 문자도 매치를 하고, 내부 프로퍼티인 dotAll 프로퍼티에 true로 설정됩니다.

  • 줄 바꿈 문자
    U+000A Line Feed(LF)("\n")
    U+000D Carriage Return(CR)("\r")
    U+2028 Line Separator
    U+2029 Paragraph Separator
const text = `line
줄을 바꿈`;
// before
console.log(/[\s\S]+/.test(text));
console.log(/[^]+/.test(text));
// true
// true
// s flag
const obj = new RegExp(".+", "s");
console.log(obj.test(text));
console.log(obj.dotAll);
// true
// true
profile
소신있게 정진합니다.
post-custom-banner

0개의 댓글