정규식(Regular Expression)

정규식

http://beemarketer.co.kr/ga/regex-verify/

정규식이란 텍스트 데이터 중에서 원하는 조건(패턴, pattern)과 일치하는 문자열을 찾아 내기 위해 사용하는 것으로 미리 정의된 기호와 문자를 이용해서 작성한 문자열을 말한다. 

 

정규식을 이용하면 많은 양의 텍스트 파일 중에서 원하는 데이터를 손쉽게 뽑아낼 수도 있고 입력된 데이터가 형식에 맞는지 체크할 수 있다. 예를 들면 html 문서에서 전화번호나 이메일 주소만을 따로 추출한다던가, 입력한 비밀번호가 숫자와 영문자의 조합으로 되어 있는지 확인할 수 있다. 

 

자바에서 정규식을 사용하려면 'java.util.regex' 패키지에 있는 'Pattern' 클래스와 'Matcher' 클래스를 사용해야 한다. 'Pattern' 클래스는 정규식 패턴을 정의하고, 'Matcher' 클래스는 해당 패턴을 대상 문자열과 비교하여 일치하는 부분을 찾는다.

 

메타문자

 

 정규식 패턴은 문자열에서 특정한 문자나 문자열 패턴을 찾기 위해 사용된다. 정규식 패턴을 작성하기 위해서는 다음과 같은 메타문자들을 이용한다. 

 

  • ` 문자 ` : Pattern에 등록되 문자만 일치함. 
String s = "ca123";
Pattern p = Pattern.compile("c");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // c
  • ` . ` : 모든 문자열과 일치함.(특수문자도 일치), 문자 사이에 입력을 하면 해당 문자사이에 어떤 문자가 와도 상관이 없음(문자열 길이만 맞추면 된다)
String s = "ca123";
Pattern p = Pattern.compile("c.");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // ca

String s = "acacb";
Pattern p = Pattern.compile("a.b"); 
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // acb
  • ` [] ` : 대괄호 안에 있는 문자 중 하나와 일치함.
String s = "c23";
Pattern p = Pattern.compile("c[123]"); // c[1|2|3], c[1-3] 도 같은 의미임.
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // c2
  • ` [^] ` : 대괄호 안에 포함된 문자를 제외한 어떤 문자 하나와 일치
String s = "c45";
Pattern p = Pattern.compile("c[^123]"); // c[^1|2|3], [^1-3] 도 같은 의미임.
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // c4
  • ` * ` : 바로 앞의 문자가 0개 이상 반복되는 패턴과 일치
String s = "b";
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // a 가 없어도 b 가 출력됨
  •  ` + ` : 바로 앞의 문자가 1개 이상 반복되는 패턴과 일치
String s = "b";
Pattern p = Pattern.compile("a+b");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // a가 없으면 출력이 안됨
  • ` ? ` : 바로 앞의 문자가 0개 또는 1개인 패턴과 일치
String s = "ab";
Pattern p = Pattern.compile("a?b");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // ab -> ab , b - > b 
  • ` {n} ` : 바로 앞의 문자가 n 번 반복하는 패턴과 일치
String s = "aaab";
Pattern p = Pattern.compile("a{3}");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // aaab -> aaa
  • ` {n,} ` : 바로 앞의 문자가 n번 이상되는 패턴과 일치
String s = "aaaaaaaaaaaaaab";
Pattern p = Pattern.compile("a{3,}");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // aaaaaaaaaaaaaab -> aaaaaaaaaaaaaa
  • ` {n,m} ` : n번 부터 m번까지 반복하는 패턴과 일치 (초과시 m번 기준으로 인식) 
String s = "aaaaaaaaaaaaaab";
Pattern p = Pattern.compile("a{1,5}");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // aaaaaaaaaaaaaab -> aaaaa
  • ` () ` : 괄호 안에 있는 패턴과 일치
String s = "abcdcdcdcdef";
Pattern p = Pattern.compile("ab(cd)+ef");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // abcdcdcdcdef -> abcdcdcdcdef
  • ` | ` : OR연산을 수행하는 패턴과 일치
String s = "abcd";
Pattern p = Pattern.compile("[a-z].*|[0-9].*");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // abcd -> abcd, 1234 -> 1234
  • ` ^ ` : 시작하는 문자와 일치
String s = "abcd";
Pattern p = Pattern.compile("^[a-z]*");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // abcd -> abcd , Aancd -> 없음
  • ` $ ` : 끝나는 문자와 일치
String s = "abcd";
Pattern p = Pattern.compile(".*[a-z]$");
Matcher m = p.matcher(s);
if (m.find()) System.out.println(m.group()); // abcd -> abcd, abcd1 -> 없음

 

특수한 문자

  • ` \d ` : 숫자와 일치
  • ` \D ` : 숫자가 아닌 문자와 일치
  • ` \w ` : 알파벳 대소문자와 숫자, 언더바(_)와 일치
  • ` \W ` : 알파벳 대소문자와 숫자, 언더바(_)를 제외한 문자와 일치
  • ` \s ` : 공백 문자(스페이스, 탭, 개행 등)과 일치
  • ` \S ` : 공백 문자를 제외한 문자와 일치

활용

자바의 String 클래스에는 문자열 내부의 일부 문자열을 다른 문자열로 바꿔주는 replace메소드와, 정규 표현식을 이용하여 일부 문자열을 다른 문자열로 바꿔주는 replaceAll 메소드가 있다. 

 

replace메소드는 매칭되는 문자열을 찾아서 모두 지정된 문자열로 바꾸는 간단한 문자열 대체 작업을 수행한다. 이 메소드는 정규식을 사용하지 않으며, 첫 번째 인수로 전달된 문자열을 찾아서 두 번째 인수로 전달되 문자열로 대체한다. 

String s = "abc";
s.replace("a", "A"); // Abc

반면에 replaceAll 메소드는 첫 번째 인수로 전달되 정규식과 매칭되는 모든 문자열을 찾아서 두 번째 인수로 전달된 문자열로 대체한다. replaceAll 메소드를 이용하면 매우 유용하다. 

String s = "...abc@13sxq13^)";
s.replaceAll("[^a-z0-9]",""); // abc13sxq13

또한 replace 메소드는 문자열에 포함된 모든 문자열을 찾아서 대체하지만, replaceAll 메소드는 정규식에 일치하는 모든 문자열만 대체한다. 

 

따라서 replace 메소드는 단순한 문자열 대체 작업을 수행하고 replaceAll 메소드는 정규식을 이용하여 문자열을 대체하는 더 복잡한 작업을 수행한다. 

 

아래 문제는 정규식을 이용하여 풀기 좋은 문제로 연습삼아 풀어 보는 것을 추천합니다. 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

'Language > Java' 카테고리의 다른 글

BigInteger, BigDecimal  (0) 2023.03.29
StringTokenizer, StringBuilder, StringBuffer  (0) 2023.03.27
(Java)10진법 <--> n집법 변환  (0) 2023.03.16
Chapter7. 객체지향 프로그래밍II  (0) 2022.12.04
Chapter5. 배열(Array)  (0) 2022.12.03