본문 바로가기

자바(JAVA)
자바(Java) 정규표현식

//정규 표현식, Regular Expression


- 정규식

- "특정 패턴"의 문자열을 검색하는 도구

- 언어나 기술에 독립적인 별도의 기술

- 유닉스


// 정규 표현식 구성요소(문법)
- 공백도 문자

1. x
- x는 임의의 1개 문자
- 고정 문자
~ "a" > a
~ "abc" >  abc


2. .
- 임의의 문자 1개
- 와일드카드(모든 문자)
~ "홍.동" > 홍길동, 홍유동, 홍순동 홍찬동 ...
~ "홍.." > 홍길동, 홍유동, 홍순동 홍찬동, 홍순신, 홍가가, 홍나나 ...


3. 출현 횟수
- 바로 앞의 문자(집합)의 출현 횟수를 표현
    a. ? 
        - 바로 앞의 대상 생략 가능, 중복 불가
        - 출현 횟수: 0~1
        ~ "a?bc" > abc 또는 bc
        ~ "(자바)?코드" ? > 자바코드 또는 코드 
 
    b. +
        - 바로 앞의 대상 생략 불가, 중복 가능
        - 출현 횟수: 1~무한대
        ~ "a+bc" > abc, aabc, aaabc ...
        ~ "(자바)+코드" ? > 자바코드, 자바자바코드, 자바자바자바코드 ...

    c. *
        - 바로 앞의 대상 생략 가능, 중복 가능
        - 출현 횟수: 0~무한대
        ~ "a*bc" > bc, abc, aabc, aaabc ...
        ~ "(자바)*코드" ? > 코드, 자바코드, 자바자바코드, 자바자바자바코드 ...
 
    d. 생략
        - 바로 앞의 대상 생략 불가, 중복 불가
        - 출현횟수: 1
        - ?, +, * 가 사용되지 않은 경우 
        ~ "a?bc"에서 bc


4. 선택, choice
    a. [열거값]
        - 열거된 값들 중 하나를 선택해서 검색 (순서 상관x)
        ~ "[129]" > 1, 2, 9 중 하나 선택해서 검색
          ~ "[0-9]" > 숫자가 있는지 검색
         ~ "[김이박]길동" > 김길동, 이길동, 박길동 검색
          ~ "[123]?45" ? 45, 145, 245, 345
          ~ "[123]+45" ? 145, 245, 345, 1245, 2345, 1345, 12345
         ~ "[123]*45" ? 45, 145, 245, 345, 1245, 2345, 1345
 
         ~ 페이지의 모든 숫자(한자리 이상) 검색 > "[0123456789]+"
 
          ~ 페이지의 모든 숫자(2자리) 검색 > "[0123456789][0123456789]"
 
          ~ 주민등록번호 > "[0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9]"
 
          ~ 전화번호 > "010-[0-9][0-9][0-9][0-9]?-[0-9][0-9][0-9][0-9]"
 
          ~ 영어 소문자 포함 > "[a-z]+"
 
          ~ 영어 대문자 포함 > "[A-Z]+"
 
          ~ 영어 소문자 > "[a-z]"
          ~ 영어 대문자 > "[A-Z]"
          ~ 영문자 > "[a-zA-Z]"
          ~ 한글 > "[가-힣]"
 
          ~ '홍'씨 성을 가지는 이름 > "홍[가-힣][가-힣]" ※"홍.."으로 검색하면 홍ab, 홍%$까지 검색한다.
 
          ~ 영어 소문자 + 숫자 > "[a-z0-9]"
         ~ 영문자 + 숫자 > "[A-Za-z0-9]"
         ~ 영문자 + 숫자 + 한글 > "[0-9a-zA-Z가-힣]"
 
         ~ 식별자로 적합한 문자(영문자 + 숫자 + _) > "[A-Za-z0-9_]"

    b. [^열거값]
        - 열거값을 제외한 나머지 검색

        ~ [^0-9] > 숫자가 아닌 모든 문자
        ~ [^A-Za-z] > 영어가 아닌 모든 문자
        ~ [^가-힣] > 한글이 아닌 모든 문자


5. 출현 횟수
    - 바로 앞의 문자(집합)의 출현 횟수를 표현
    - ?, +, * 보다 더 세밀한 패턴을 지정 가능> ?, +, * 로 할 수 있는 건 ?, +, *로 하되, 못 하는 것들을 할 때 활용한다.

    a. {n} 
        - n: 출현 횟수 > 고정
        ~ "a{1}bc" > abc
        ~ "a{2}bc" > aabc
        ~ "a{3}bc" > aaabc 

    b. {n,m}
        - n: 최소 출현 횟수
        - m: 최대 출현 횟수 
        ~ "a{1,2}bc" ? abc, aabc
        ~ "a{2,3}bc" ? aabc, aaabc

    c. {n,}
        - n: 최소 출현 횟수
        - 최대 출현 횟수: 무한대
        ~ "a{1,}bc" ? abc, aabc, aaabc ...
        ~ "a{2,}bc" ? aabc, aaabc, aaaabc ...
 
         ~ 주민등록번호 > "[0-9]{6}-[0-9]{7}"
 
        ~ 전화번호 > "010-[0-9]{3,4}-[0-9]{4}"
 
         ~ 영어단어 첫문자는 대문자로 시작, 나머지는 소문자로 한 개 이상 > "[A-Z][a-z]{1,}"

 
6. 처음과 끝
    a. ^ 
        - 뒤에 오는 표현으로 반드시 시작해야 함.
        - str.startsWith()과 같은 역할
        ~ "^홍길동" > str.startsWith("홍길동")

    b. $ 
        - 앞에 오는 표현으로 반드시 끝나야 함.
        - str.endsWith()와 같은 역할
        ~ "홍길동$" str.endsWith("홍길동")
 
 
7. 줄임 표현
    a. \d or \d
        - Digit > 숫자
        ~ "\d" > "[0-9]"
        ~ "\D" > "[^0-9]"

        ~ 주민번호 > "\d{6}-\d{7}"

    b. \w or \W
        - Word > 영문자 + 숫자 + _
        ~ "\w" > "[A-Za-z0-9_]"
        ~ "\W" > "[^A-Za-z0-9_]"


    c. \s or \S
        - 공백문자 > 스페이스, 탭, 엔터
        ~ "\s" > 공백문자
        ~ "\S" > 공백문자 제외


//자바의 정규표현식


a. 기존(문자열) 메서드 > 정규표현식 지원  
    ~ split
    ~ replaceAll

b. 정규표현식 클래스
    1. 정규식 객체 생성
        ~ Pattern p1 = Pattern.compile(regex);
    2. 객체가 자신의 정규식으로 txt 검사
        ~ Matcher m1 = p1.matcher(txt);
        ~ boolean m1.find() > iterator의 hasNext()와 비슷한 역할을 함 > while문을 통해 몇 번 발견했는지도 알 수 있음.
        ~ m1.group() > 찾은 데이터를 반환함
        ~ m1.group(n) > 정규식에서 () 를 찾아서 n번째를 반환함(0은 그냥 group()과 같음)


package com.test.java;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Ex93_RegEx {

	public static void main(String[] args) {

		m5();
	

	} //main

	private static void m5() {
		
		//정규표현식 객체

		String txt = "안녕하세요. 홍길동입니다. 제 연락처는 010-1234-5678입니다. 혹시 이 번호로 연락이 안 되면 010-5656-9876으로 연락주세요.";
		
		
		//txt 안에 전화번호가 포함되어 있는지 검사?
		String regex = "([0-9]{3})-([0-9]{3,4})-([0-9]{4})";
		
		//정규식 객체 생성
		Pattern p1 = Pattern.compile(regex);
		
		//p1이 자신의 정규식으로 txt를 검사한다.
		Matcher m1 = p1.matcher(txt);
		
//		if(m1.find()) {
//			System.out.println("전화번호 발견!");
//		} else {
//			System.out.println("전화번호가 없습니다.");
//		}
		
//		System.out.println(m1.find()); //010-1234-5678
//		System.out.println(m1.find()); //010-5656-9876
//		System.out.println(m1.find());
		
//		int count = 0;
//
//		while(m1.find()) {
//			count++;
//		}
//
//		System.out.println(count);
		
		while(m1.find()) {
			System.out.println("전화번호: " + m1.group());
			System.out.println("통신사: " + m1.group(1));
			System.out.println("가운데 자리: " + m1.group(2));
			System.out.println("끝자리: " + m1.group(3));
			System.out.println();
		}
		
	}
	
}

package com.test.java;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Ex93_RegEx {

	public static void main(String[] args) {

		m6();	

	} //main

	private static void m6() {
		
		String txt = "안녕하세요. 저는 홍길동입니다. 네? 당신 이름도 길동이라구요? 아 ~ 김길동이군요. 마침 저쪽에도 최길동이 있습니다. 어? 남궁길동도 있네요.";
		
//		String regex = "[홍김최]?길동";
		String regex = "(홍|김|최|남궁)(길동)";
		
		Pattern p1 = Pattern.compile(regex);
		
		Matcher m1 = p1.matcher(txt);
		
		while(m1.find()) {
			System.out.println("찾은 이름: " + m1.group());
			System.out.println("성: " + m1.group(1));
			System.out.println("이름: " + m1.group(2));
			System.out.println();
		}
		
	}
	
}

package com.test.java;

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Ex93_RegEx {

	public static void main(String[] args) {

		m7();
		
	

	} //main

	private static void m7() {
		
		//회원가입 > 유효성 검사
		//1. 이름 	> 필수 입력, 한글, 2-5자 이내
		//2. 나이 	> 필수 입력, 숫자, 18세 이상
		//3. 아이디	> 필수 입력, 영어+숫자+_, 숫자로는 시작 불가능, 4-12이내
		
		System.out.println("[회원 가입]");
		
		Scanner scan = new Scanner(System.in);
		
		System.out.print("이름: ");
		String name = scan.nextLine().trim();
		
		System.out.print("나이: ");
		String age = scan.nextLine().trim();
		
		System.out.print("아이디: ");
		String id = scan.nextLine().trim();
		
		if(isValid(name, age, id)) {
			System.out.println("가입 완료");
		} else {
			System.out.println("가입 실패");
		}
		
		//날짜(2023-03-03) > "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
		//시간(14:30) > "^[0-9]{1}:[0-9]{2}$"
		
	}

	private static boolean isValid(String name, String age, String id) {
		
		String regex = "";		//정규식
		Pattern pattern = null;	//정규식 객체
		Matcher matcher = null;	//결과 객체

		//1. 이름 	> 필수 입력, 한글, 2-5자 이내
		regex = "^[가-힣]{2,5}$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(name);  //입력 값을 대상으로 정규식 검사
		
		if(!matcher.find()) {
			//유효성 만족 xx
			System.out.println("이름 필수 입력, 한글 2-5자 이내로 입력하세요.");
			return false;
		}
		
		//2. 나이 	> 필수 입력, 숫자, 18세 이상
		regex = "^[0-9]{2,}$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(age);
		
		if(!matcher.find() || (Integer.parseInt(age) < 18)) {
			//유효성 만족 xx
			System.out.println("나이 필수 입력, 18세 이상의 숫자를 입력하세요.");
			return false;
		}
		
		
		//3. 아이디	> 필수 입력, 영어+숫자+_, 숫자로는 시작 불가능, 4-12이내
		regex = "^[A-Za-z_][A-Za-z0-9]{3,11}$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(id);
		
		if(!matcher.find()) {
			//유효성 만족 xx
			System.out.println("아이디 필수입력, 영어+숫자+_ 4-12자 이내로 입력하세요.(숫자로 시작 불가능)");
			return false;
		}	
		
		return true;
	}
	
}

'자바(JAVA)' 카테고리의 다른 글

[자바(Java)] Collection 총 정리  (0) 2023.02.28
[자바(Java)] static  (0) 2023.02.20
[자바(Java)] equals , hashcode  (0) 2023.02.19
[자바(Java)] 동기화  (0) 2023.02.19
[자바(Java)] 디버그(debug)  (0) 2023.02.09