[javascript] 정규표현식 질문

조회수 546회

안녕하세요. 아래의 코드는 핸드폰 번호를 입력할때 XXX-XXXX-XXXX , (번호와 번호끼리는 -,/,\를 통해 연결될수있음) 로 입력되었는지를 확인하는 코드인데요.

var re = /(?:\d{3}|\(\d{3}\))([-\/\.])\d{4}\1\d{4}/;  
var OK = re.exec('010-8269-0021');  

var re = /(?:\d{3})([-\/\.])\d{4}\1\d{4}/;  
var OK = re.exec('010-8269-0021');  

var re = /\d{3}([-\/\.])\d{4}\1\d{4}/;  
var OK = re.exec('010-8269-0021');  

사실 이 코드중 위의 코드는, 아래 mdn에 나와있는 예제코드 입니다. https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/%EC%A0%95%EA%B7%9C%EC%8B%9D#special-negated-character-set

바로 이 부분인데요.

입력을 확인하기 위해 특수 문자를 사용하기섹션

다음 예에서, 사용자는 전화번호를 입력 할 것으로 예상됩니다. 사용자가 "Check" 버튼을 누를 때, 스크립트는 번호의 유효성을 검사합니다. 번호가 유효한 경우(정규식에 의해 지정된 문자 시퀀스와 일치합니다), 스크립트는 사용자에게 감사하는 메시지와 번호를 확인하는 메시지를 나타냅니다. 번호가 유효하지 않은 경우, 스크립트는 전화번호가 유효하지 않다는 것을 사용자에게 알립니다.

비 캡처링 괄호 (?: , 정규식은 세 자리 숫자를 찾습니다 \d{3} OR | 왼쪽 괄호( 세 자리 숫자 다음에 \d{3}, 닫는 괄호 다음에 ), (비 캡처링 괄호를 종료)) 안에, 하나의 대시, 슬래시, 또는 소수점을 다음과 같이 발견했을 때, 세 자리 숫자 다음에 d{3}, 대시의 기억 매치, 슬래시, 또는 소수점 다음에 \1, 네 자리 숫자 다음에 \d{4} 문자를 기억합니다([-\/.]).

사용자가 키를 누를 때 활성화 변경 이벤트는 RegExp.input의 값을 설정합니다.

<!DOCTYPE html>
<html>  
  <head>  
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
    <meta http-equiv="Content-Script-Type" content="text/javascript">  
    <script type="text/javascript">  
      var re = /(?:\d{3}|\(\d{3}\))([-\/\.])\d{3}\1\d{4}/;  
      function testInfo(phoneInput){  
        var OK = re.exec(phoneInput.value);  
        if (!OK)  
          window.alert(OK.input + " isn't a phone number with area code!");  
        else
          window.alert("Thanks, your phone number is " + OK[0]);  
      }  
    </script>  
  </head>  
  <body>  
    <p>Enter your phone number (with area code) and then click "Check".
        <br>The expected format is like ###-###-####.</p>
    <form action="#">  
      <input id="phone"><button onclick="testInfo(document.getElementById('phone'));">Check</button>
    </form>  
  </body>  
</html>

질문1) : (?:\d{3}|\(\d{3}\)(?:\d{3})의 차이는 무엇인가요? 도저히 모르겠습니다.

질문2) 위 예제에서 (?:\d{3})가 필요한가요? 그냥 \d{3}를 써도 되지 않나요?

(?: exp)를 사용하는 이유는 /foo{1,2}/라면, {1,2}는 'foo'의 마지막 'o' 에만 적용되므로 /(?:foo){1,2}/ 와 같이 괄호처럼 묶어서 사용하고 싶을때 쓰는것으로 알고 있습니다.

위의 문제에서는 굳이 (?:) 를 사용할 필요가 있는지도 모르겠네요.

질문 읽어주셔서 감사합니다! 좋은 하루보내세요.

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • 질문1의 답

    • (?:\d{3})123, 990 같은 게 매칭됩니다. (646)은 매칭되지 않습니다.
    • (?:\d{3}|\(\d{3}\)123, (990) 같은 게 매칭됩니다.

    \뭐를 쓰면 문자 그대로의 를 찾습니다. (는 regex 특수기호이므로, 그걸 '찾고' 싶다면 \를 붙여서 이스케이프 해줘야 합니다.


    질문2의 답
    예제의 regex는 아마도, /(?:\d{3}|\(\d{3}\))/ 구문을 통해서, 이런 걸 캡쳐하고 싶었던 듯합니다.

    • 326
    • (010)

    하지만 동시에 이런 건 캡쳐하면 안되는 거죠.

    • 02
    • 045)
    • 0일0
    • 1234

    이걸 달성하기 위해 구성된 최종 구문이 /(?:\d{3}|\(\d{3}\))/인 겁니다. 이 구문은 이렇게 구성되어 있거든요.

    1. (?:어쩌구)어쩌구를 몽땅다 캡쳐해라.
    2. 어쩌구|저쩌구어쩌구 아니면 저쩌구를 찾아라.
    3. \d{3} → 숫자 3개를 찾아라.
    4. \(\d{3}\) → 괄호로 싸인 숫자 3개를 찾아라.

    답변이 됐을지 모르겠네요. https://regex101.com 같은곳을 이용해 여러 테스트 케이스를 직접 해보세요.

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)