Node.JS) Regex(정규 표현식)
Programming/JS

Node.JS) Regex(정규 표현식)

728x90

목차

     


     

    2022.05.04 - [Programming/BACKEND] - Node.JS)05.02-04( expressServer - ORM, SNS서비스 만들기, sequelize, passport 활용(localStrategy), )

     

    1. 정규 표현식

    • '정규 표현식'은 '문자표현공식', '문자탐색공식'이라고 부르는 연산식과 같은 분류언어입니다.
    • 전문가가 사용한는 정규표현식은 초보자에게 외계언어와 같은 느낌의 어려운 공식이지만 문자탐색과 스캔에 있어서 강력한 기능을 갖고있어서, 여러 분야에서 많이 사용되고 있습니다.
    • 자바스크립트에서도 많은 '다양한 정규표현식의 적용을 지원'하고 있다.

     


     

    2. 정규 표현식 사용 방법

    2.1. 기본적인 키워드 찾기

    string.match(/정규식/);  <- 문자열에서 모든 일치를 담은 배열을 반환한다. (일치가 없으면 null 반환)

    • g : global ; 모든 패턴에 대해 '전역 탐색'을 한다.
      다시 말해, 문자열 전체를 검색하여 지정한 정규표현식 패턴과 일치한 문자열을 찾아 배열에 담는다.
    • i : ignoreCase ; 대소문자 구분하지 않는다는 설정.
    var a = "While some may view this debt forgiveness as a slap in the face to people who were responsible and paid off their student loans";
    
    var b = a.match(/a/);   // a 변수 안의 String 내용 중 'a' 글자를 검색 매칭해주세요
    console.log(b);  // '12'(번째에 있다 -> index=12)
    
    b = a.match(/th/);   // a 변수 안의 String 내용 중 'th' 글자를 검색 매칭해주세요
    console.log(b); // '20'(번째에 있다 -> index=20)
    
    b = a.match(/is/g);   // a 변수 안의 String 내용 중 'th' 글자를 검색 매칭해주세요
    console.log(b); // [ 'is' ]
    
    var a = "gabbvdrfabgrdsagfrea";
    var c = a.match(/ab*/g);   // a변수 안의 String 에서 'a'로 시작하고 'b'가 몇 개든 반복되는 글자를 검색.
    console.log(c); // [ 'abb', 'ab', 'a', 'a' ]

     


     

    2.2. [ ] : 문자 탐색에 사용하는 대괄호

    • [ ] : 리스트에서 사용했던 대괄호로 표현
    • [ ] 대괄호 안에 검색하고자 하는 글자들을 넣고, 그 포함 유무를 판단한다.
    // [abc] : 'a'와 'b'와 'c'가 대상 문자열 안에 하나라도 포함되었는지 판단한다.
    
    let string = 'a';
    match = string.match(/[abc]/g);
    console.log(match);	//[ 'a' ]
    
    string = 'Before';
    match = string.match(/[abc]/gi);
    console.log(match);	//[ 'B' ]
    
    string = 'dude';
    match = string.match(/[abc]/g);
    console.log(match);	//null
    • abc 처럼 [ ]가 없는 경우 'abc'단어를 의미하지만
    • [ abc ]는 'a' 또는 'b' 또는 'c'를 의미한다.

     

    a = 'a';
    c = a.match(/[abc]/g);
    console.log(c);     // [ 'a' ]
    
    a = 'before';
    c = a.match(/[abc]/g);
    console.log(c);     // [ 'b' ]
    
    a = 'dude';
    c = a.match(/[abc]/g);
    console.log(c);     // null
    
    a = 'before';
    c = a.match(/abc/g);
    console.log(c);     // null
    
    a = 'grezageagfvrzce';
    c = a.match(/z[abc]/g);
    console.log(c);     // [ 'za', 'zc' ]
    
    // 정규표현식 패턴 끝에 'g'를 쓰면 매칭된 결과를 배열로 하여 모두 찾아내어 담아낸다.
    // 'g'가 없으면 맨 첫번째 매칭된 결과를 보여주고, 그 위치값을 index로 보여준다.

     

     


    2.3. 자주 사용하는 문자열 패턴

    [0-9] 숫자와 매치, 0부터 9까지 아라비아 기호 매칭
    = [0123456789] 라고 써야하지만 줄여서 사용하는 것이다.
    [a-z]  문자 소문자와 매치, 소문자 a 부터 z까지의 글자 매칭
    = [abcdefghijklmnopqrstuvwxyz]
    [A-Z] 문자 대문자와 매치, 대문자 A 부터 Z까지의 글자 매칭
    = [ABCDEFGHIJKLMNOPQRSTUVWXYZ]
    [a-zA-Z] 아라비아 숫자를 제외한 대소문자와 매칭
    [a-zA-Z0-9] 아라비아 숫자, 소문자, 대문자 모두 매칭
    \d  숫자와 매치
    = [0-9]와 동일한 표현이다.
    \D 숫자가 아닌것과 매치
    \s whitespace(공백)와 매치
    = [\t\n\r\f\v]와 같은 표현
    \S whitespace(공백)가 아닌것과 매치
    \w 문자와 숫자들과 매치 [0-9a-zA-Z]와 같은 표현
    \W 문자와 숫자가 아닌 것과 매치
    // 소문자 검색
    a = 'ABCDEfGH';
    b = a.match(/[a-z]/g);
    console.log(b);     // [ 'f' ]
    
    // 숫자 검색
    a = 'ABCDEfGH0';
    // b = a.match(/[0-9]/g);
    b = a.match(/[\d]/g);
    console.log(b);     // [ '0' ]
    
    // 공백 검색
    a = 'ABCDE fGH';
    b = a.match(/[\s]/g);
    console.log(b);     // [ ' ' ]
    
    // 글자(문자와 숫자) 검색
    a = '$#%^$!%^k&$%(';
    b = a.match(/[\w]/g);
    console.log(b);     // [ 'k' ]

     


    2.4. Dot( . )

    • Dot(.) - 줄 바꿈 글자인 '\n'을 제외한 모든 글자와 매칭된다.
    • /a.b/ : a와 b 사이에 어떤 글자가 들어와도 매칭된다.
    • a + "모든문자" + b
    string = 'aab';
    match = string.match(/a.b/g);
    console.log(match); //[ 'aab' ]
    
    string = 'a0b';
    match = string.match(/a.b/g);
    console.log(match); //[ 'a0b' ]
    
    string = 'ab';
    match = string.match(/a.b/g);
    console.log(match); //null

     

    2.4.1. a.b와 a[.]b의 차이점

    • [ . ] : 괄호안에 '\n'을 제외한 모든 문자를 표시하는 것이 아닌, 괄호안의 ' . '을 찾는 것.
      • 'a.b'는 매칭이 되지만 'aab'는 매칭되지 않는다.
    a = 'aab';
    b = a.match(/a.b/g);
    console.log(b);     // [ 'aab' ]
    
    a = 'aab';
    b = a.match(/a[.]b/g);
    console.log(b);     // null
    
    a = 'a0b';
    b = a.match(/a.b/g);
    console.log(b);     // [ 'a0b' ]
    
    a = 'a.b';
    b = a.match(/a.b/g);
    console.log(b);     // [ 'a.b' ]
    
    a = 'ab';
    b = a.match(/a.b/g);
    console.log(b);     // null

     


     

    2.5. 반복 ( * )와 ( + ) 

    * 앞에 있는 글자의 반복 횟수를 '0회차부터 카운트'하여 반복된 문자열을 탐색
    + 앞에 있는 글자의 반복 횟수를 '1회차부터 카운트'하여 반복된 문자열을 탐색
    // 정규표현식이 'ca*t'일 경우
    
    string = 'ct';
    match = string.match(/ca*t/g);
    console.log(match); //[ 'ct' ]
    
    string = 'cat';
    match = string.match(/ca*t/g);
    console.log(match); //[ 'cat' ]
    
    string = 'caaaaat';
    match = string.match(/ca*t/g);
    console.log(match); //[ 'caaaaat' ]
    
    
    // 정규표현식이 'ca+t' 일 경우
    
    string = 'ct';
    match = string.match(/ca+t/g);
    console.log(match); // null
    
    string = 'cat';
    match = string.match(/ca+t/g);
    console.log(match); //[ 'cat' ]
    
    string = 'caaaat';
    match = string.match(/ca+t/g);
    console.log(match); //[ 'caaaat' ]

     

    a = 'caaaat';
    b = a.match(/ca*t/g);
    console.log(b);     // [ 'caaaat' ]
    
    a = 'caaaat';
    b = a.match(/ca+t/g);
    console.log(b);     // [ 'caaaat' ]
    
    a = 'ct';
    b = a.match(/ca*t/g);
    console.log(b);     // [ 'ct' ]
    
    a = 'ct';
    b = a.match(/ca+t/g);
    console.log(b);     // null

     


     

    2.6. 반복 {m,n}와 ( ? )

    {m}
    앞에 위치한 글자의 m회 반복 매칭
    {m,n}
    앞에 위치한 글자의 m회부터 n회 반복 매칭
    ?
    앞에 위치한 글자의 0회 또는 1회 반복 매칭

     

    // 정규표현식 : 'ca{2}t'
    string = 'cat';
    match = string.match(/a{2}/g);
    console.log(match); // null
    
    string = 'caat';
    match = string.match(/a{2}/g);
    console.log(match); // [ 'aa' ]
    
    
    // 정규표현식 : 'ca{2,4}t'
    string = 'cat';
    match = string.match(/ca{2,4}t/g);
    console.log(match); // null
    
    string = 'caat';
    match = string.match(/ca{2,4}t/g);
    console.log(match); // [ 'caat' ]
    
    string = 'caaaat';
    match = string.match(/ca{2,4}t/g);
    console.log(match); // [ 'caaaat' ]
    
    string = 'caaaaat';
    match = string.match(/ca{2,4}t/g);
    console.log(match); // null
    
    
    // 정규표현식 : 'ca?t'
    string = 'ct';
    match = string.match(/ca?t/g);
    console.log(match); // [ 'ct' ]
    
    string = 'cat';
    match = string.match(/ca?t/g);
    console.log(match); // [ 'cat' ]
    
    string = 'caat';
    match = string.match(/ca?t/g);
    console.log(match); // null

     

    a = 'caat';
    b = a.match(/ca{2}t/g);
    console.log(b);     // [ 'caat' ]
    
    a = 'caaat';
    b = a.match(/ca{2,4}t/g);
    console.log(b);     // [ 'caaat' ]
    
    a = 'caaaat';
    b = a.match(/ca{2,4}t/g);
    console.log(b);     // [ 'caaaat' ]
    
    a = 'caaaaaat';
    b = a.match(/ca{2,4}t/g);
    console.log(b);     // null
    
    a = 'ct';
    b = a.match(/ca?t/g);
    console.log(b);     // [ 'ct' ]

     


     

    2.7. 연습문제

    2.7.1. 연습문제1

    • 아래 문자열 중 이름을 제외한 전화번호만 추출하여 출력한다.
    a = "park chan ho 010-1234-5678 kim min 010-8888-9999 lee 011-123-2222";
    a = "park chan ho 010-1234-5678 kim min 010-8888-9999 lee 011-123-2222";
    b = a.match( /\d{3,4}-\d{3,4}-\d{3,4}/g);
    console.log(b);

     

    2.7.2. 연습문제2

    • 아래 문자열 중 이름을 제외한 이메일주소만 추출하여 출력한다.
    a = "park chan ho park@naver.com kim min kim@daum.net lee lee@myhome.com";
    a = "park chan ho park@naver.com kim min kim@daum.net lee lee@myhome.com";
    b = a.match( /\w*@\w*[.]\w*/g);
    console.log(b);

     


     

    2.8. 메타 문자 ( |, ^, $,  \b, \B )

    2.8.1. |

    • | : or의 의미로 사용.
      •  'a|b'는 'a 또는 b'의 의미
    let a = "Hello World";
    let b = a.match( /Hello|Crow/g);
    console.log(b); //[ 'Hello' ]
    
    a = "Welcome Crow";
    b = a.match( /Hello|Crow/g);
    console.log(b); //[ 'Crow' ]
    
    a = "Hello Crow";
    b = a.match( /Hello|Crow/g);
    console.log(b); //[ 'Hello', 'Crow' ]​

     

    2.8.2. ^ 

    •  ^ : ^abc 는 abc로 시작하는 의미의 정규식
    a = "Life is too short";
    b = a.match(/^Life/g);
    console.log(b); // [ 'Life' ]

     

    2.8.3. $

    • $ : abc$ 는 abc로 끝나는 의미의 정규식
    a = "Life is too short";
    b = a.match(/short$/g);
    console.log(b); // [ 'short' ]

     

    2.8.4. \b

    • \b : Word Boundary 의미로 whitespace로 식별되는 메타 문자
      • * 원래 문자열 안에 사용하는 \b는 백스페이스의 역할을 하는 이스케이프 문자이지만
      • * 정규표현식에서는 공백의 의미로 사용된다.
    a = "no class are all class";
    b = a.match(/\bclass\b/g);
    console.log(b); // [ 'class', 'class' ]
    
    a = "the declassified algorithm";
    b = a.match(/\bclass\b/g);
    console.log(b); // null
    
    a = "one subclass is";
    b = a.match(/\bclass\b/g);
    console.log(b); // null

     

    2.8.5. \B

    • \B : whitespace로 구분되지 않는(공백이 아닌 것), 그 외 다른 글자로 구분되는 정규식
    a = "no class are all class";
    b = a.match(/\Bclass\B/g);
    console.log(b); // null
    
    a = "the declassified algorithm";
    b = a.match(/\Bclass\B/g);
    console.log(b); // [ 'class' ]
    
    a = "one subclass is";
    b = a.match(/\Bclass\B/g);
    console.log(b); // null

     


     

    3. 전후방탐색

    • 정규표현식으로 구분해내고 매칭한 결과 내용 중, '정규표현식에서 사용되었던 글자를 제외한 나머지를 결과로 얻고자 할 때'
    • 예를 들어 http://www.naver.com 에서 "글자들이 반복되고 ' : ' 로끝남"이라는 정규식이 있다면 결과는 'http:' 가 될테지만 원하는 결과가 ' : '를 제외한 'http'만을 목적으로 할 때 사용하는 방식이다.
    let a = 'http://www.naver.com';
    // '.' : \n이 아닌 모든 글자
    let b = a.match(/.+:/g);
    console.log(b); // [ 'http:' ]
    
    // 위 결과에서 ':'를 없애고 싶을 때는?  -> '전방탐색'을 사용한다.
    // 정규식 : (?=정규식 또는 글자)
    // 조건에 매칭된 후, 해당(?= 뒤로 이어진) 정규식에 있는 글자는 소모하지 않는다(취하지 않는다)
    
    a = 'http://www.naver.com';
    // '.' : \n이 아닌 모든 글자
    b = a.match(/.+(?=:)/g);
    console.log(b); // [ 'http' ]

    3.1. 긍정 / 부정 탐색

    전방 긍정 탐색
    (전방 탐색)
    (?=value) 문장에서 value(표현식)값과 일치하는 값을 찾고, 그 앞(왼쪽)으로 찾고자 하는 문자를 매칭한다.
    전방 부정 탐색 (?!value) 문장에서 value(표현식)값과 일치하지 않는 값을 찾고, 그 앞(왼쪽)으로 찾고자 하는 문자를 매칭한다.
    후방 긍정 탐색
    (후방 탐색)
    (?<=value) 문장에서 value(표현식)값과 일치하는 값을 찾고, 그 뒤(오른쪽)로 찾고자 하는 문자를 매칭한다.
    후방 부정 탐색 (?<!value) 문장에서 value(표현식)값과 일치하지 않는 값을 찾고, 그 뒤(오른쪽)로 찾고자 하는 문자를 매칭한다.
    // 전방 긍정 탐색
    a ='스크램블 에그 | 단백질: 10g, 지방: 20g\n햄버거 | 단백질: 40g, 탄수화물: 50g, 지방: 30g\n우유 | 단백질: 20g, 탄수화물: 5g, 지방: 20g';
    b = a.match(/(?=.*단백질)(?=.*탄수화물)(?=.*지방).*/gm);
    console.log(b); 
    // [
    //   '햄버거 | 단백질: 40g, 탄수화물: 50g, 지방: 30g',
    //   '우유 | 단백질: 20g, 탄수화물: 5g, 지방: 20g'
    // ]
    
    // 전방 부정 탐색
    a ='스크램블 에그 | 단백질: 10g, 지방: 20g\n햄버거 | 단백질: 40g, 탄수화물: 50g, 지방: 30g\n우유 | 단백질: 20g, 탄수화물: 5g, 지방: 20g';
    b = a.match(/(?=.*단백질)(?!.*탄수화물)(?=.*지방).*/gm);
    console.log(b); 
    // [ '스크램블 에그 | 단백질: 10g, 지방: 20g' ]
    
    // 후방 긍정 탐색
    a ='스크램블 에그 | 단백질: 10g, 지방: 20g\n햄버거 | 단백질: 40g, 탄수화물: 50g, 지방: 30g\n우유 | 단백질: 20g, 탄수화물: 5g, 지방: 20g';
    b = a.match(/.+(?<=단백질.*)(?<=지방.*)/gm);
    console.log(b); 
    // [
    //     '스크램블 에그 | 단백질: 10g, 지방: 20g',
    //     '햄버거 | 단백질: 40g, 탄수화물: 50g, 지방: 30g',
    //     '우유 | 단백질: 20g, 탄수화물: 5g, 지방: 20g'
    // ]
    
    // 후방 부정 탐색
    a ='스크램블 에그 | 단백질: 10g, 지방: 20g\n햄버거 | 단백질: 40g, 탄수화물: 50g, 지방: 30g\n우유 | 단백질: 20g, 탄수화물: 5g, 지방: 20g';
    b = a.match(/.+(?<=단백질.*)(?<!탄수화물.*)(?<=지방.*)/gm);
    console.log(b); 
    // [ '스크램블 에그 | 단백질: 10g, 지방: 20g' ]

     


     

    3.2. 크롤링 ( 웹 데이터 추출 )

    • 주로 html에서 html 태그를 취하지 않고 내용만 발췌할 때 자주 사용한다( 크롤링 )
    • 줄이 나뉘어진 데이터를 한줄로 잇고 싶다면 '\'(백슬러쉬)를 활용한다.
      • 그러나 데이터가 줄이 나뉜채로 하나의 데이터로 저장하고 싶다면 '\n\'를 활용한다. (줄을 나눈 뒤 잇기)
    a= '<html>\n\
    <head>\n\
    <title>안녕하세요 반갑습니다</title>\n\
    </head>\n\
    <body>\n\
    <div>웹사이트에서 내용을 발췌한다.</div>\n\
    </body>\n\
    </html>\n';
    console.log(a);
    
    
    // 전후방탐색 적용X
    b=a.match(/<div>.+<\/div>/g);
    console.log(b);   // [ '<div>웹사이트에서 내용을 발췌한다.</div>' ]
    
    // 전후방탐색 (?<=value), (?=value)을 활용
    b=a.match(/(?<=<div>).+(?=<\/div>)/g);
    console.log(b);   // [ '웹사이트에서 내용을 발췌한다.' ]
    
    // 타이틀을 발췌하여 출력
    b = a.match(/(?<=<title>).+(?=<\/title>)/g);
    console.log(b); // [ '안녕하세요 반갑습니다' ]

     


     

    3.3. 연습문제

    3.3.1. 연습문제 1~5

    a = '일반텍스트 파일 : abc.txt, 자동실행파일 : autoexe.bat, 데이터분석파일 : bigdata.at, 더미파일 : gfreag, 알수없는 파일 : korea.bar';
    
    
    // 연습문제1
    // a변수에서 '파일이름.확장자명' 으로 구성된 파일명만 골라서 출력하세요 
    b = a.match(/\b\w*[.]\w+/g);    // [ 'abc.txt', 'autoexe.bat', 'bigdata.at', 'korea.bar' ]
    console.log(b);
    
    // 연습문제2
    // 파일의 확장자가 'b로 시작하는 파일'을 찾아 출력
    b = a.match(/\b\w*[.]b\w+/g);    // [ 'autoexe.bat', 'korea.bar' ]
    console.log(b);
    
    // 연습문제3
    // 파일의 확장자가 'b로 시작하지 않는 파일'을 찾아 출력
    b = a.match(/\b\w*[.][^b]\w+/g);    // [ 'abc.txt', 'bigdata.at' ]
    console.log(b);
    
    // 연습문제4
    // 파일의 확장자가 'a 또는 b로 시작하는 파일'을 찾아 출력
    b = a.match(/\b\w*[.](a|b)\w+/g);    // [ 'autoexe.bat', 'bigdata.at', 'korea.bar' ]
    console.log(b);
    
    // 연습문제5
    // 파일의 확장자가 'a로 시작하거나, b로 시작하지 않는 파일'을 찾아 출력
    b = a.match(/\b\w*[.](a|[^b])\w+/g);    // [ 'abc.txt', 'bigdata.at' ]
    console.log(b);

     

    3.3.2. 연습문제 6~7

    a = '박길동 : park@naver.com, 김하나 : kim@daum.net, 김둘 : ee@myhome.co.kr, 웹사이트 : http://abcdefg.co.kr';
    
    
    // 연습문제6
    // 이메일 주소만 탐색하여 출력
    b = a.match(/\b\w*[@]\w+([.]\w*){1,2}/g);    // [ 'park@naver.com', 'kim@daum.net', 'ee@myhome.co.kr' ]
    console.log(b);
    
    // 연습문제7
    // 이메일 주소 중 .net과 .com만 골라 출력
    b = a.match(/\b\w*[@]\w+[.](com|net)/g);    // [ 'park@naver.com', 'kim@daum.net' ]
    console.log(b);

     

    3.3.3. 연습문제 8

    a = '현재 접속중인 외부 아이피는 121.66.42.195 이며, 내부 아이피는 192.168.0.2 입니다.';
    
    // 연습문제8
    // 위 내용에서 아이피주소만 매칭하여 출력
    b = a.match(/\d+[.]\d+[.]\d+[.]\d+/g);    // [ '121.66.42.195', '192.168.0.2' ]
    // b = a.match(/[012][0-9][0-9][.] ... /g);    // [ '121.66.42.195', '192.168.0.2' ]
    console.log(b);

     


     

    4. replace( ) 함수

    let a = 'blue sock and red shocks';
    
    b = a.replace(/blue|white|red/g, 'color');
    console.log(b); // color sock and color shocks

     


     

    4.1. 연습문제

    4.1.1. 연습문제1

    a= 'park 010-1234-5678 , kim 010-8888-9999 , lee 010-1111-2222 ';
    
    // 정규표현식과 replace를 이용하여 전화번호 뒷자리를 모두 마스킹(*로 치환)해주세요.
    b = a.replace(/[-]\d{4}\s/g, '-****');
    console.log(b)  // park 010-1234-****, kim 010-8888-****, lee 010-1111-****

     

    4.1.2. 연습문제2

    a= '네이버 - http://www.naver.com , 다음 - http://www.daum.net , 네이트 - http://www.nate.com';
    
    // 위 문자열에서 http를 모두 https로 치환하여 출력
    b = a.replace(/\bhttp(?=:)/g, 'https');
    console.log(b)  // 네이버 - https://www.naver.com , 다음 - https://www.daum.net , 네이트 - https://www.nate.com

     

    300x250