관련 지식
regex, regular expression

만약 텍스트에 있는 모든 금액을 찾고 싶을때 아래와 같이 할 수 있습니다.

  1. var regex1 = RegExp('[0-9]+','g');
  2. var array1;
  3. while((array1 = regex1.exec(str)) != null) {
  4. console.log(array1[0]);
  5. }

그러나 위의 정규표현식은 ‘숫자’를 찾을 뿐 모든 숫자가 금액을 뜻하지는 않습니다. 금액을 찾기 위해 정규식을 조금 변경합니다.

  1. var regex1 = RegExp('[0-9]+원','g');

그런데 위와 같이 찾을 경우 숫자뿐 아니라 화폐 단위인 ‘원’까지 리턴됩니다. 단위는 필요 없는데 말이죠. 이때 전방탐색/후방탐색을 사용하면 됩니다.

전방탐색

전방탐색은 패턴과 일치하지만 값으로 리턴하지는 않는 정규식 패턴을 의미 합니다. 위에서 언급한 금액 찾기를 예로 들겠습니다. 우리는 금액을 찾기 위해 ‘원’을 포함한 숫자를 찾지만 ‘원’ 자체는 받고 싶지 않습니다. 이렇게 하면 됩니다.

  1. var regex2 = RegExp('[0-9]+(?=원)','g');

전방탐색은 (?=정규식) 형태로 사용합니다. 정규식에는 매칭 조건에는 넣고 싶지만 리턴받고 싶지 않은 정규식을 넣으면 됩니다.

이때 주의해야 할것은 전방탐색 정규식의 위치입니다. 흔히 문자열의 왼쪽을 전방, 오른쪽을 후방이라고 생각하기 쉽지만 그렇지 않습니다.

문자열 탐색은 왼쪽에서 오른쪽으로 진행합니다.(인덱스가 0 에서부터 큰 쪽으로) 따라서 매칭 패턴을 기준으로 탐색방향이 전방탐색이 되고 반대쪽이 후방탐색이 됩니다.

후방탐색

샘플소스에서 사용하는 문자열에는 ‘포인트 xxxx원’ 과 같은 문자열도 있습니다. 따라서 포인트만 구분하도록 해보겠습니다. 매칭되는 문자열의 후방(검색 방향과 반대방향)에 ‘포인트 ‘ 문자열이 있는지 확인하면 됩니다.

  1. var regex3 = /(?<=포인트 )[0-9]+/g;

후방탐색은 전방탐색에 ‘<’를 추가해서 (?<=정규식) 형태로 사용하면 됩니다. 다만 주의하실점이 하나 있습니다. 오래된 자바스크립트 엔진에서는 이와같은 긍정형 후방탐색이 불가능합니다. 익스플로러 11은 오류가 발생하지만 크롬에선 문제 없습니다. node.js의 경우 8.9.4 버전에서 ‘invalid group’ 오류가 발생하지만 10.15.3 버전에서는 문제 없이 작동합니다.

부정형 탐색

위의 예는 일치하는 패턴을 찾는 긍정형 전방/후방탐색 방법이었습니다. 이번에는 부정형 탐색을 알아보겠습니다. 금액에 해당하는 ‘XXX원’ 이 아닌 모든 숫자를 찾으려고 합니다. 어떻게 할까요?

  1. var regex4 = /[0-9]+(?![0-9]*원)/g; //부정형 전방탐색

위 정규표현식은 ‘원’으로 끝나는 숫자를 제외한 모든 숫자를 찾는 패턴입니다. 날짜, 단순 숫자등이 리턴됩니다. 부정현 전방탐색은 (?!정규식) 형태를 사용하면 됩니다.

이번엔 포인트를 제외한 모든 금액을 찾는 정규식을 작성해보겠습니다. 부정형 후방탐색은 (?<!정규식) 을 사용하면 됩니다.

  1. var regex5 = /(?<!포인트 [0-9]*)[0-9]+(?=원)/g; //부정형 후방탐색

포인트가 아닌 숫자에는 날짜와 단순 숫자도 있으므로 긍정형 전방탐색을 같이 이용했습니다.

정리

전방탐색 식을 먼저 외우고 ‘<’ 만 추가하면 후방탐색이 된다고 외우면 좀 쉬울것 같습니다.

후방탐색전방탐색
긍정형(?<=정규식)(?=정규식)
부정형(?<!정규식)(?!정규식)

샘플

  1. var str = ' \
  2. 7750 생활/건강 > 악기 > 타악기 > 스틱/스탠드 \
  3. 리뷰2 등록일 2018.09. 찜하기 0 신고하기 \
  4. 네이버페이 포인트 87 \
  5. 배송비 2500 \
  6. 적립 쿠폰 할인 구매정보 10800 \
  7. 생활/건강 > 악기 > 타악기 > 스틱/스탠드 \
  8. 등록일 2019.01. 찜하기2 신고하기 \
  9. 네이버페이 포인트 216 배송비 무료 \
  10. 적립 쿠폰 할인 구매정보 \
  11. ';
  12. // var p = str.matchAll(/[0-9]+원/);
  13. // console.log(p);
  14. var regex1 = /[0-9]+원/g;
  15. print(regex1);
  16. var regex2 = /[0-9]+(?=원)/g; //긍정형 전방탐색
  17. print(regex2);
  18. var regex3 = /(?<=포인트 )[0-9]+/g; //긍정형 후방탐색
  19. print(regex3);
  20. var regex4 = /[0-9]+(?![0-9]*원)/g; //부정형 전방탐색
  21. print(regex4);
  22. var regex5 = /(?<!포인트 [0-9]*)[0-9]+(?=원)/g; //부정형 후방탐색
  23. print(regex5);
  24. function print(regex) {
  25. console.log("-----------------");
  26. var array1;
  27. while((array1 = regex.exec(str)) != null) {
  28. console.log(array1[0]);
  29. }
  30. }