반응형
정규표현식(RegExp : Regular Expression)
특정 규칙을 가진 문자열 집합에 대한 표현식. 유효성 검사, 검색, 문자열 대체 등에 유용
언어독립적. 간결하게 복잡한 조건을 검사가능. 문법자체가 복잡하므로 학습 비용이 비교적 높음




정규표현식 객체 생성하기
<button id="btn1">정규표현식 객체</button>
btn1.addEventListener('click',(e)=>{
//숫자포함여부 검사용 정규표현식
const regexp1 = /[0-9]/gi;
const regexp2 = new RegExp(/[0-9]/gi);
const regexp3 = new RegExp("[0-9]","gi");
console.dir(regexp1);
console.dir(regexp2);
console.dir(regexp3);
});

모두 똑같이 표현되는 것을 확인할 수 있다.
"gi"를 플래그 라고 한다.
btn1.addEventListener('click',(e)=>{
//숫자포함여부 검사용 정규표현식
const regexp1 = /[0-9]/gi;
const regexp2 = new RegExp(/[0-9]/gi);
const regexp3 = new RegExp("[0-9]","gi");
//정규식
console.log(regexp1.test("abcde"));//false
console.log(regexp1.test("hello123",regexp1.lastIndex));//true 한개라도 해당되면 true
console.log(regexp1.exec("hello123",regexp1.lastIndex));//매칭결과를 배열로 변환
console.log(regexp1.exec("hello123",regexp1.lastIndex));
console.log(regexp1.exec("hello123",regexp1.lastIndex));
});

정규식 테스트는 1개라도 해당이 되면 true를 리턴한다.
regexp1.lastIndex 는 매칭의 결과를 배열로 변환한다.
lastIndex를 계속 입력할 경우 그다음인덱스, 그다음 인덱스, ... 를 반환하고
"hello123"보다 긴 인덱스를 찾을 경우 null을 반환한다.
.search : 처음 일치한 인덱스 반환
.replace(정규표현식,"바꿀문자") : 일치하는 부분 바꿀문자로 변환
split(/[ ]/) : [ ] 안에 들어가는 값으로 split
match : 일치하는 요소를 배열로 변환
btn1.addEventListener('click',(e)=>{
//숫자포함여부 검사용 정규표현식
const regexp1 = /[0-9]/gi;
const regexp2 = new RegExp(/[0-9]/gi);
const regexp3 = new RegExp("[0-9]","gi");
//문자열
console.log("hello123".search(regexp1));//5 처음 일치한 인덱스 반환
console.log("hello123".replace(regexp1,"*"));//hello*** 일치하는 부분을 *으로 변환
console.log("a,p/p l,e".split(/[,/ ]/));//['a','p','p','l','e']
console.log("hello123".match(regexp1));//일치하는 요소를 배열로 반환 ['1','2','3']
});

대체문자
- String#replace시 사용
- $& 매칭된 문자열
- $` 매칭 이전 문자열
- $' 매칭 이후 문자열
btn2.addEventListener('click',(e)=>{
const str="javascript jquery ajax css sass";
const regexp=/as/g;
area2.innerHTML=`${str.replace(regexp,"<mark>$&</mark>")}<br/>`;
area2.innerHTML+=`${str.replace(regexp,"<mark>$`</mark>")}<br/>`;
area2.innerHTML+=`${str.replace(regexp,"<mark>$'</mark>")}<br/>`;
area2.innerHTML+=`${str.replace(regexp,(matched)=>`<mark>${matched}</mark>`)}<br/>`;
});

/as/g : as를 전역으로 찾음
flag 문자 (정규표현식 옵션)
- g global : 전역비교수행. 여러건 매칭을 처리. g가 없으면 첫 매칭만 처리
- i ignoreCase : 영문자에 한해 대소문자 구분하지 않고 처리
- m multiLine : 여러줄인 경우(\n) 행단위로 처리
const SUBSTITUTE = "<mark>$&</mark>";
btn3.onclick=(e)=>{
const str="Javascript jQuery Ajax Sass";
area3.innerHTML =`${str.replace(/a/g,SUBSTITUTE)}<br>`;
area3.innerHTML +=`${str.replace(/a/g,SUBSTITUTE)}<br>`;
area3.innerHTML +=`${str.replace(/a/gi,SUBSTITUTE)}<br>`; //대문자도 포함
}

anchor
- ^ 시작
- $ 끝
btn4.onclick=(e)=>{
const str="Javascript xxx jQuery Ajax";
area4.innerHTML=`${str.replace(/^j/i,SUBSTITUTE)}<br/>`;//i안붙이면 해당사항없
area4.innerHTML+=`${str.replace(/x$/,SUBSTITUTE)}<br/>`;
const str2=`Javascript
xxx
jQuery
Ajax`; //탭안쓰고 바짝붙여써야 플래그 실행됨
area4.innerHTML+=`${str2.replace(/^j/img,SUBSTITUTE)}<br/>`; //플래그 사이 순서 상관없
// m = 줄단위 수행. 엔터쳐야 의미있음
area4.innerHTML+=`${str2.replace(/x$/gm,SUBSTITUTE)}<br/>`;
};

.(온점) : 임의의 한글자 의미
문자, 특수문자, 공백문자 하나를 가리킴
개행문자(\n)는 임의의 글자에 포함되지 않음. 띄어쓰기는 포함
btn5.onclick=(e)=>{
const regexp =/^a.b/;
console.log("acb",regexp.test("acb"));//true
console.log("acbc",regexp.test("acbc"));//true
console.log("acbcccccccc",regexp.test("acbcccccccc")); //true
console.log("aaba",regexp.test("aaba"))//true
console.log("ab",regexp.test("ab"))//false
console.log("a b",regexp.test("a b"))//true
console.log("a\nb",regexp.test("a\nb"))//false
const regexp2=/in.$/; //in다음에 한글자 있고 끝이나는 문자열 검사
console.log("going",regexp2.test("going")); //true
console.log("inner",regexp2.test("inner")); //f
console.log("holidayin",regexp2.test("holidayin"));//f
}

[ ]
하나의 문자에 대한 값목록(순서상관없음), 범위(아스키코드(유니코드)작은순-큰순) [abc] [김이]
[^abc] [ ]안에 사용된 ^은 반전을 의미. abc가 아닌 문자
btn6.onclick=(e)=>{
const str="Javascript jQuery Ajax 12345 안녕 ㄱㄴㄷ ㅏㅔㅣㅗㅜ";
area6.innerHTML=`${str.replace(/[0123456789]/g,SUBSTITUTE)}<br/>`;
area6.innerHTML+=`${str.replace(/[0-9]/g,SUBSTITUTE)}<br/>`;
area6.innerHTML+=`${str.replace(/[A-Za-z]/g,SUBSTITUTE)}<br/>`;//범위쓸때는 (유니코드)작은값부터 큰값으로
area6.innerHTML+=`${str.replace(/[a-z]/gi,SUBSTITUTE)}<br/>`;
area6.innerHTML+=`${str.replace(/[가-힣ㄱ-ㅎㅏ-ㅣ]/g,SUBSTITUTE)}<br/>`;//자모음분리상태는 이걸로 체크 불가
//@실습문제
//1. 알파벳소문자로 시작하는 문자열 여부검색
const re1=/^[a-z]/g;
console.log(re1.test("abcde"));//true
console.log(re1.test("123qwerty"));//false
console.log(re1.test("Hello World"));//f
console.log(re1.test("aㅏㅏㅏㅏㅏㅏ"));//true
console.log(re1.test("ㄱaaaㄹaaaa"));//f
//2. 숫자 4자리 여부 검사
const re2=/^[0-9][0-9][0-9][0-9]$/g;
console.log(re2.test("1234"));//t
console.log(re2.test("123456"));//f
console.log(re2.test("abcd"));//f
console.log(re2.test("12"));//f
console.log(re2.test("가나다라"));//f
};


단축문자
- \d digit : 숫자 한글자
- \w word : 영문자/숫자/_ 한글자
- \s space : 공백문자/개행문자/탭문자 한글자
- \D : 숫자아닌 한글자
- \W : 영문자, 숫자, _ 아닌 한글자
- \S : 공백문자, 개행문자, 탭문자가 아닌 한글자
btn7.onclick=(e)=>{
const str = `A1 B2 c3 d_4 e:5 fG12345 -@!@#$%
안녕 잘가
水`;
area7.innerHTML=`${str.replace(/\d/g,SUBSTITUTE)}<br/>`;
area7.innerHTML+=`${str.replace(/\D/g,SUBSTITUTE)}<br/>`;
area7.innerHTML+=`${str.replace(/\w/g,SUBSTITUTE)}<br/>`;
area7.innerHTML+=`${str.replace(/\W/g,SUBSTITUTE)}<br/>`;
area7.innerHTML+=`${str.replace(/\s/g,SUBSTITUTE)}<br/>`;
area7.innerHTML+=`${str.replace(/\S/g,SUBSTITUTE)}<br/><br/>`;
//[]문법
area7.innerHTML += `${str.replace(/[0-9]/g, SUBSTITUTE)}<br/>`;
area7.innerHTML += `${str.replace(/[^0-9]/g, SUBSTITUTE)}<br/>`;
area7.innerHTML += `${str.replace(/[A-Za-z0-9_]/g, SUBSTITUTE)}<br/>`;
area7.innerHTML += `${str.replace(/[^A-Za-z0-9_]/g, SUBSTITUTE)}<br/>`;
area7.innerHTML += `${str.replace(/[ \n\t]/g, SUBSTITUTE)}<br/>`;
area7.innerHTML += `${str.replace(/[^ \n\t]/g, SUBSTITUTE)}<br/>`;
}

( ) grouping , | or
btn8.onclick = (e) => {
const str = '월요일에는 월요병, 화가 부르르르 화요일 홧병, 수수술한잔 하는 수요일, 목이 컥~ 목요일, 금방 오지 않는 금요일, 그리고 오늘은 월요일';
area8.innerHTML = `${str.replace(/(수요일|목요일|금요일)/g, SUBSTITUTE)}<br/>`;
area8.innerHTML += `${str.replace(/(수|목|금)요일/g, SUBSTITUTE)}<br/>`;
area8.innerHTML += `${str.replace(/[수목금]요일/g, SUBSTITUTE)}<br/>`;
// String#match:매칭된 결과를 배열로 반환
console.log(str.match(/(월요일|화요일)/g));
};

escaping
- wildcard문자를 문자그대로 사용하고자 하는 경우 \와 함께 escaping할 수 있다.
- [ ]안에서 escaping 필요없음. (단 \\ 처리 필요)
btn9.onclick = (e) => {
const str = '\\3.4^2$';
area9.innerHTML = `${str.replace(/\$/, SUBSTITUTE)}<br>`;
area9.innerHTML += `${str.replace(/\./, SUBSTITUTE)}<br>`;
area9.innerHTML += `${str.replace(/\\/, SUBSTITUTE)}<br>`;
area9.innerHTML += `${str.replace(/\^/, SUBSTITUTE)}<br>`;
area9.innerHTML += `${str.replace(/[$]/, SUBSTITUTE)}<br>`;
area9.innerHTML += `${str.replace(/[.]/, SUBSTITUTE)}<br>`;
area9.innerHTML += `${str.replace(/[\\]/, SUBSTITUTE)}<br>`;
area9.innerHTML += `${str.replace(/[\^$]/g, SUBSTITUTE)}<br>`;
area9.innerHTML += `${str.replace(/[$^]/g, SUBSTITUTE)}<br>`;
};

수량자 Quantifier
- a* a가 0개이상
- a+ a가 1개이상
- a? a가 0,1개
- a{2,5} a가 2개이상 5개이하
- a{2, } a가 2개이상
- a{3} a가 3개
a{ , 5}a가 5개 이하 (지원하지 않는 문법)
btn10.onclick = () => {
const str = "aabc abc bc";
area10.innerHTML = `${str.replace(/a*b/g, SUBSTITUTE)}<br/>`;
area10.innerHTML += `${str.replace(/a+b/g, SUBSTITUTE)}<br/>`;
area10.innerHTML += `${str.replace(/a?b/g, SUBSTITUTE)}<br/>`;
// @실습문제
// a로 시작하고, z로 끝나는 문자열 검사
const regexp = /^a.*z$/;
console.log(regexp.test("abcdefz")); // true
console.log(regexp.test("a*z")); // true
console.log(regexp.test("az")); // true
console.log(regexp.test("abc")); // false
console.log(regexp.test("xyz")); // false
console.log(regexp.test("안a하b이c녕z")); // false
console.log("-----------------------")
// 영문자만으로 이루어진 문자열 검사
const regexp2 = /^[A-Za-z]+$/;
console.log(regexp2.test("abcde"));
console.log(regexp2.test("a"));
console.log(regexp2.test(""));
console.log(regexp2.test("123"));
console.log(regexp2.test("abc123"));
};


btn11.onclick = () => {
const str = "aa aba abba abbba";
area10.innerHTML = `${str.replace(/ab{0,}a/g, SUBSTITUTE)}<br>`;
area10.innerHTML += `${str.replace(/ab*a/g, SUBSTITUTE)}<br>`;
area10.innerHTML += `${str.replace(/ab{1,}a/g, SUBSTITUTE)}<br>`;
area10.innerHTML += `${str.replace(/ab+a/g, SUBSTITUTE)}<br>`;
area10.innerHTML += `${str.replace(/ab{0,1}a/g, SUBSTITUTE)}<br>`;
area10.innerHTML += `${str.replace(/ab?a/g, SUBSTITUTE)}<br>`;
area10.innerHTML += `${str.replace(/ab{1}a/g, SUBSTITUTE)}<br>`;
// 4자리 숫자로 이루어진 비밀번호 검사
const regexp1 = /^\d{4}$/;
console.log("1234", regexp1.test("1234")); // true
console.log("123456", regexp1.test("123456")); // false
console.log("abcd", regexp1.test("abcd")); // false
console.log("12", regexp1.test("12")); // false
console.log("가나다라", regexp1.test("가나다라")); // false
console.log("----------------------------------")
// 숫자로 시작하고 영문자가 3개이상 나오고, .로 끝나는 문자열 검사
const regexp2 = /^\d[a-zA-Z]{3,}\.$/;
console.log("9abcdefg.", regexp2.test("9abcdefg.")); // true
console.log("9abc.", regexp2.test("9abc.")); // true
console.log("100", regexp2.test("100")); // false
console.log("1가나다.", regexp2.test("1가나다.")); // false
console.log("123abc가나다.", regexp2.test("123abc가나다.")); // false
};


Look Around
검사만 실시하고 최종 결과에 포함되지 않는 것.
- Look Ahead
- a(?=b) b가 뒤따르는 a를 조회
- a(?!b) b가 뒤따르지 않는 a를 조회
- Look behind
- (?<=b) a앞에 b가 존재하는 a를 조회
- (?<! b) a앞에 b가 존재하지 않는 a를 조회
btn12.onclick = () => {
const str1 = 'hello world hello Tom hello Jane';
area12.innerHTML = `${str1.replace(/hello(?= world)/g, SUBSTITUTE)}<br>`;
area12.innerHTML += `${str1.replace(/hello(?! world)/g, SUBSTITUTE)}<br>`;
const str2 = 'hello world lotte world t world';
area12.innerHTML += `${str2.replace(/(?<=hello )world/g, SUBSTITUTE)}<br>`;
area12.innerHTML += `${str2.replace(/(?<!hello )world/g, SUBSTITUTE)}<br>`;
};

*비밀번호 유효성 검사*
ex ) 8~12자리, 숫자/영문자/특수문자(!&/\*@)가 하나이상 포함된 비밀번호
<input type="text" name="password" id="password" placeholder="비밀번호">
password.onblur = (e) => {
const val = e.target.value;
if(!/^.{8,12}$/.test(val)){
alert("비밀번호는 8 ~ 12자리여야 합니다.");
return;
}
if(!/\d/.test(val)){
alert("비밀번호는 하나이상의 숫자를 포함해야 합니다.");
return;
}
if(!/[a-z]/i.test(val)){
alert("비밀번호는 하나이상의 영문자를 포함해야 합니다.");
return;
}
if(!/[!&/\\*@]/i.test(val)){
alert("비밀번호는 하나이상의 특수문자(!&/\\*@)를 포함해야 합니다.");
return;
}
console.log("비밀번호가 유효합니다.");
};










반응형