정규표현식

정규 표현식 - Java

  • -
반응형

이번 포스트에서는 자바 언어에서 정규 표현식 처리를 위한 API에 대해 알아보자.  자바에서 정규 표현식을 처리하기 위해서는 java.util.regex 패키지에 있는 Matcher와 Pattern을 사용한다.

 

java.util.regex.Pattern

 

matches()

Pattern 클래스는 크게 compile, matcher, matches 메서드를 제공한다.

먼저 간단히 주어진 문자열이 특정 패턴에 부합하는지 알아보기 위해서는 matches 메서드를 사용한다.

public static boolean matches(String regex, CharSequence input) {
  Pattern p = Pattern.compile(regex);
  Matcher m = p.matcher(input);
  return m.matches();
}

matches는 input의 전체 내용이 완벽하게 regex에 부합하는지를 살펴본다.

@Test
public void testPatternMatches() {
  String pattern = "[a-z]{2,5}";
  String [] strs = {"henry", "Hello"};
  assertTrue(Pattern.matches(pattern, strs[0]));  
  assertFalse(Pattern.matches(pattern, strs[1])); // 부분 일치, 전체는 불일치
}

matches는 위 예에서 보듯이 전체 일치 여부만을 판단하는 단순한 상황에서 간단히 사용해볼 수 있는 메서드이다.  하지만 matches의 메서드 구현부를 살펴보면 자바에서 정규 표현식을 어떻게 써야햐는지 단계를 잘 보여준다. compile()을 통해 표현식을 생성한 후 Matcher를 이용해 일치 여부를 판단하는 형식이다.

 

compile() 

compile 계열의 메서드는 정규표현식 자체를 만드는 static 메서드로 pattern만을 이용하거나 flag를 추가할 수 있다. flag 를 추가할 때는 비트연산자를 이용한다. (global은 기본적으로 적용된다.)

public static Pattern compile(String regex) {
  return new Pattern(regex, 0);
}
    
public static Pattern compile(String regex, int flags) {
  return new Pattern(regex, flags);
}

다음은 Pattern 객체 생성 예이다.

Pattern p1 = Pattern.compile("[가-힣]{2,5}", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);

 

 

matcher()

Pattern의 matcher() 메서드는 Matcher 객체를 얻는 메서드로 Matcher에는 정규식과 테스트 문자의 일치 여부에 대한 자세한 정보가 담긴다. 

@Test
public void useMatcherTest() {
  String pattern = "[a-z]{2,5}";
  String [] strs = {"henry", "Hello"};
  Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); // flag 활용 가능
  Matcher m = p.matcher(strs[0]);
  assertTrue(m.matches());
  m = p.matcher(strs[1]);
  assertTrue(m.matches());
}

 

java.util.regex.Matcher

 

객체의 생성

상세한 일치 정보를 위해서는 java.util.regex.Matcher 클래스를 사용한다. Matcher는 앞서 살펴봤던 Pattern의 matcher 메서드를 통해서 얻을 수 있다.

String src = "그는 10살이고 1000원이 있다.";
String regexp = "\\d{1,}";
Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(src);

 

matches() vs find()

Matcher를 이용해 문자열을 검사할 때는 matches()와 find()가 대표적인 메서드이다. matches는 Pattern의 matches와 동일하게 테스트 문자열이 패턴에 완전히 부합하는지를 살펴본다. 반면 find테스트 문자열에 패턴에 해당하는 부분이 있는지 찾아본다.

System.out.printf("%s는 %s패턴인가? %b%n", src, regexp, matcher.matches());
System.out.printf("%s에서 %s패턴을 발견할 수 있나? %b%n", src, regexp, matcher.find());    

// 그는 10살이고 1000원이 있다.는 \d{1,}패턴인가? false
// 그는 10살이고 1000원이 있다.에서 \d{1,}패턴을 발견할 수 있나? true

용도에 따라 적절하게 matches()나 find()를 사용하자.

정규표현식에 부합했다면 그 결과는 MatchResult에서 확인할 수 있다. matches()에 대한 일치 여부는 Matcher.toMatchResult()에서 확인할 수 있고 find()에 대한 결과는 Matcher.results()에서 반환되는 Stream<MatchResult>를 이용한다.

MatchResult는 start()와 end()를 이용해서 일치하는 부분의 위치를 파악할 수 있다.(Matcher를 통해서도 바로 확인 할 수 있다.)

@Test
public void testStream() {
  String src = "그는 10살이고 1000원이 있다.";
  String regexp = "\\d{1,}";
  Matcher m = Pattern.compile(regexp).matcher(src);
  Stream<MatchResult> stream = m.results();
  stream.forEach(mr -> {
    int start = mr.start();
    int end = mr.end()   ;
    log.info("일치 ({}~{}) : {}", start, end, src.substring(start, end) );
  });
}

 

변경

마지막으로 문자열의 내용 중 패턴과 일치하는 값을 다른 값으로 변경하려는 경우는 replaceAll, replaceFirst를 사용한다.

String replaced = matcher.replaceAll("[숫자위치]");
System.out.printf("전체 변경 결과:%s%n", replaced);

replaced = matcher.replaceFirst("[Number Here]");
System.out.printf("처음만 변경 결과:%s%n", replaced);

//전체 변경 결과:그는 [숫자위치]살이고 [숫자위치]원이 있다.
//처음만 변경 결과:그는 [Number Here]살이고 1000원이 있다.

 

String에서의 정규 표현식 사용

 

프로그래밍 하다보면 가장 많이 사용되는 것이 문자열이 주어진 패턴에 부합하는가를 물어보는 내용인데 이런 간단한 처리를 위해서는 String 클래스의 matches 메서드를 사용하는 것이 가장 간단하다.

@Test
public void testStringRegex() {
  String src = "$10,000";
  String regexp = "^\\$[0-9,]{1,}";
  assertTrue(src.matches(regexp));
}

반응형

'정규표현식' 카테고리의 다른 글

정규 표현식 - SQL  (0) 2020.06.13
정규 표현식 - JavaScript  (0) 2020.06.11
정규 표현식 - 유용한 표현들  (1) 2020.06.10
정규 표현식 - 메타문자  (0) 2020.06.10
정규 표현식 - 개요  (1) 2020.06.09
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.