이번엔 이 공부 끝내겠다 시리즈/정규표현식

string을 정규표현식 변환하기

by GicoMomg (Lux) 2021. 12. 29.

이번 시간에는 string 문자나 정규표현식을 정규표현식으로 변경해주는 코드를 살펴보자

1. 언제 유용할까?

  • string 문자(’feat’) 혹은 string 타입의 정규표현식(’/feat/’)은 정규표현식 함수를 바로 쓸 수 없다.
  • 그렇기 때문에 string타입의 문자 혹은 정규표현식을 정규표현식으로 변환해야하는데, 어떤 경우에 변환하는 코드를 쓰는 걸까?
  • 대체로 입력값을 string 타입만 받을 수 있는 경우일 것이다.
  • 대표적으로 github actions의 경우, 인자를 string으로만 받을 수 있기 때문에 github actions에서 입력값으로 정규표현식을 받으려면 ‘/feat/’ 형태로 써야한다.
  • 하지만 ‘/feat/’형태로 받으면 정규표현식 함수를 쓸 수 없다.

🤔 왜 string타입의 정규표현식은 바로 쓸 수 없을까?

  • 그 이유는 typeof를 해보면 쉽게 알 수 있는데, 문자는 타입이 string이지만 정규표현식은 타입이 object이다.
  • 이 말은 곧 정규표현식을 string타입으로 선언하면 사용할 수 없다는 뜻이 된다.
const string = '/feat/';
const regex = /feat/;

console.log(typeof string, typeof regex)


🚫 new RegExp()string을 받아서 정규표현식으로 바꿀 수 있는데, 이걸 사용하면 안될까? 안된다!

  • '/feat/'new RegExp('/feat/') 로 하면 /feat/가 나올 거 같지만 결과는 그렇지 않다.
const string = '/feat/';

console.log(new RegExp(string))


🏃🏻 그럼 변환 코드는 어떻게 구성해야할까? 본격적으로 코드를 살펴보자




2. string을 정규표현식으로 변환하기

1) 전체 코드보기

  • convertToRegExp(string타입_정규표현식) 형태로 사용하면 된다.
function convertToRegExp(text) {
  if (text.match(/^\/.+\/[gmixXsuUAJ]*$/)) {
    return regexParser(text);
  } else return new RegExp(text, 'g');
}

function regexParser(text) {
  const m = text.match(/(\/?)(.+)\1([a-z]*)/i);
  if (m[3] && !/^(?!.*?(.).*?\1)[gmixXsuUAJ]+$/.test(m[3])) {
    return RegExp(text);
  } else {
    return new RegExp(m[2], m[3]);
  }
}

  • 사용한 모습은 아래와 같다.
console.log(convertToRegExp('feat'))       // /feat/
console.log(convertToRegExp('/^[a-z]/i'))  // /^[a-z]/i



2) 코드 상세보기

(1) convertToRegExp함수

🛠️ convertToRegExp()word가 string 혹은 string 정규표현식인지 체크하여, 정규표현식으로 변환한다.

function convertToRegExp(word) {
  if (word.match(/^\/.+\/[gmixXsuUAJ]*$/)) {    // [1]
    return regexParser(word);                   // [2]
  } else return new RegExp(word, 'g');          // [3]
}

[1]

: word/로 시작하고 /로 끝나며, 만약 flag(/g, /i 등)을 가지는지 체크한다.

: /^\/.+\/[gmixXsuUAJ]*$/ 정규표현식을 자세히 보면 의미는 아래와 같다.


[2] 만약 string형태의 정규표현식이면 regexParser()를 사용해 변환된 정규표현식을 리턴한다.

[3] string 형태의 문자라면 new RegExp을 사용해 정규표현식을 한다.



(2) regexParser함수

🛠️ regexParser()에서는 string 정규표현식을 정규표현식으로 변경한다.

function regexParser(word) {
  const m = word.match(/(\/?)(.+)\1([a-z]*)/i);                // [1]
  if (m[3] && !/^(?!.*?(.).*?\1)[gmixXsuUAJ]+$/.test(m[3])) {  // [2]
    return RegExp(word);
  } else {
    return new RegExp(m[2], m[3]);                             // [3]
  }
}

[1]

: 주어진 word가 정규식에 매치되는 경우를 array로 보여준다.

const m = word.match(/(\/?)(.+)\1([a-z]*)/i); // [1]

: /(\/?)(.+)\1([a-z]*)/i는 자세히 보면 아래와 같다.


: 만약 word/feat/를 넣고, m을 출력해보면 아래와 같이 나타난다.


[2]

: 유효치 않은 flag를 가진 정규표현식인 경우에 RegExp(word)를 한다.

if (m[3] && !/^(?!.*?(.).*?\1)[gmixXsuUAJ]+$/.test(m[3])) {  // [2]
  return RegExp(word);                                       // [2]
 } 

: m[3]의 경우, 시작/가 있고 마지막 /뒤에 문자가 있는 경우에 존재한다. (ex. /feat/g, /ass/hhhh)

: 만약 word에 '/^hi$/i'가 넣으면 m은 아래와 같은 형태가 된다.


: !/^(?!.*?(.).*?\1)[gmixXsuUAJ]+$/.test(m[3])은 유효치 않은 flag인지 체크한다.

// ex. 유효치 않은 flag를 쓴 형태

/ass/h        // h flag는 존재하지 않음
/asdadccc/ssf // ssf flag는 존재하지 않음

[3] 유효한 정규표현식 형식인 경우 new RegExp(m[2], m[3])를 사용해 정규표현식을 만든다.

...
else {
  return new RegExp(m[2], m[3]);                             // [3]
}



반응형

댓글