티스토리 뷰

728x90

자바에서 문자열에서 특정 조건에 따라 배열로 변환하는 방법에 대해서 알아보겠습니다. 

주로 split() 함수를 사용하게 되는데요, 하나의 특정 문자열 기준으로 추출하는 방법은 쉽습니다. 

// 콤마(,) 기준으로 배열로 변환하기 

String text = "김갑수,이문수,박명수,유재석,노홍철";

String[] strList = text.split(",");

 

하지만 조건이 좀 더 복잡해진다면? 

예를들어 문자열 "1D2S#10S" 에서 연속된 숫자만 추출한다고 해봅시다. 

숫자사이에 '숫자를 제외한 영문 또는 특수문자' 를 기준으로 추출한다면... 음 좀 어려워집니다. 

그럴때! 정규표현식을 이용하는 방법을 사용하면 간단해집니다. 


먼저 기본적인 정규식의 문법을 살펴봅시다. 

<정규표현식 설명>

정규표현식 표현 설명
^x
문자열이 x로 시작합니다
x$
문자열이 x로 끝납니다. 
.x
임의의 한 문자를 표현합니다. 
[x가 마지막으로 끝납니다.]
x+
x가 1번 이상 반복합니다. 
x?
x가 존재하거나 존재하지 않습니다.
x*
x가 0번이상 반복합니다. 
[xy]
x,y중 하나를 찾습니다.
^가 존재하면 not을 나타냅니다.
[^xy]
x,y를 제외하고 문자 하나를 찾습니다.
[x-z]
x~z 사이의 문자중 하나를 찾습니다.
\^
^(특수문자)를 식에 문자 자체로 포함합니다. (문자열 escape)
(x)
괄호안의 문자를 하나의 문자로 인식합니다. (괄호안을 그룹화)
x|y
x 또는 y를 찾습니다. 
(or연산자를 의미합니다.)
\s
공백 문자
\S
공백 문자가 아닌 나머지 문자
\w
알파벳이나 문자
\W
알파벳이나 숫자를 제외한 문자
\d
[0-9] 숫자
\D
숫자를 제외한 모든 문자
x{n}
x를 n번 반복한 문자를 찾습니다.
x{n,}
x를 n번이상 반복한 문자를 찾습니다. 
x{n,m}
x를 n번 이상 m번 이하 반복한 문자를 찾습니다. 

 


 

그럼 다시 "1D2S#10S" 에서 연속된 숫자만 추출해봅시다. 

위의 표에서 조건을 살펴봅니다. 
우리의 목표는 연속된 숫자를 제외한 문자들을 delimiter(구분점)로 두려고 합니다. 

위의 표를 살펴보면, '\D' 가 숫자를 제외한 모든 문자라고 써있습니다.
또한 한자리 이상이 될 수 있기 때문에 조건을 더 찾아보면, '+' 가 앞 문자가 1개 이상인 조건이란걸 찾을 수 있습니다. 

그러면 위에 표에서 알아낸 두가지 조건으로 코드를 작성해보겠습니다. 

String num = "1D2S#10S*";
String regExp = "\\D+";

String[] arr = num.split(regExp);

출력결과


<잠깐! 위의 코드 regExp = "\\D+" 에서 백슬래쉬가 왜 두번 들어가냐고요?>

문자열 Escape 라는것을 알고 계셔야 합니다. 

자바에서는 String 문자열을 표현할 때, 따옴표(") 로 감싸주게 됩니다.  (따옴표는 영어로 double quote입니다.)

그런데, 문자열중에도 따옴표를 표시하고 싶다면? 

String text = "철수는 "안녕하세요!!" 라고 인사했습니다.";

위의 코드는 자바 문법에 어긋났기 때문에 컴파일 에러를 발생시킵니다. 

따라서 아래와 같이 변경해야합니다. 

String text = "철수는 \"안녕하세요!!\" 라고 인사했습니다.";

출력: 철수는 "안녕하세요!!" 라고 인사했습니다.

이렇게 문법에 어긋나는 특수문자들을 문자로 표현하기 위해서는 역슬래쉬(\)를 특수문자 앞에 붙이는 것을 문자열 Escape라고 합니다. 

문자열 안에 역슬래쉬를 표한하고 싶다면 아래와 같이 선언하면 됩니다. 

String text = "역슬래쉬는 \\입니다.";

출력: 역슬래쉬는 \입니다.

 

다시 돌아와서, 응용을 해보도록 하겠습니다. 

"1D2S#10S" 에서 연속된 숫자를 Delimiter로 배열을 추출해 보겠습니다.  (위의 문제와 반대)

String num = "1D2S#10S*";
String regExp = "[0-9]+";

String[] arr = num.split(regExp);

출력 결과

출력 결과에서 숫자로 시작할 때, 빈 배열이 0번째 index에 들어가긴 하지만, 어쨋든 배열 추출을 완료했습니다.

 

 


<특정 문자열 사이의 문자열 추출하기 >

수직선(|) 문자 사이의 회사명을 추출하는 예제를 살펴보겠습니다. ( |회사명| )

String str = "|마이크로소프트||애플||페이스북||네이버|";
Pattern pattern = Pattern.compile("[|](.*?)[|]");

Matcher matcher = pattern.matcher(str);

while (matcher.find()) {
    System.out.println(matcher.group(1));

    if (matcher.group(1) == null) break;
}


// 출력결과
마이크로소프트
애플
페이스북
네이버
String str = "|마이크로소프트||애플||페이스북||네이버|";
Pattern pattern = Pattern.compile("[|](.*)[|]");

Matcher matcher = pattern.matcher(str);

while (matcher.find()) {
    System.out.println(matcher.group(1));

    if (matcher.group(1) == null) break;
}


// 출력결과
마이크로소프트||애플||페이스북||네이버

 

<위의 정규식 "[|](.*?)[|]" 은 무슨 뜻인가요? >

양쪽이 수직선 [|] 이고, 그 사이의 문자열은 .*? 인 것을 찾으라는 의미입니다. (아래 예제는 .*)

 

< .*과 .*?의 의미란?>

위에 정규표현식에서 응용해서 해석해보겠습니다.  

1) .* : 임의의 문자가 0번이상 반복합니다. 

해당 정규식을 Greedy Operator라고 불립니다. 작대기(|) 사이의 모든것을 가져오는 것이죠. 

2) .*? : 임의의 문자가 0번이상 반복하거나, 존재하지 않습니다. (? 뭔말인지..)

해당 정규식은 Non-greedy Operator 라고 불립니다.  최소 조건 만족을 가져온다고 보면 됩니다. 

 


<심화> 

문자열 중, window98, windowXP, window7 의 문자열을 추출하시오. 

Matcher 클래스의 group() 함수란? 

group(0): 그루핑의 모든 조건을 가져온다.
group(1): 그루핑의 첫번째 조건을 가져온다. (그루핑 조건이 하나만 존재한다면, group(0) == group(1) 일 것이다.) 
group(2): 그루핑의 두번째 조건을 가져온다. 
... index는 그루핑 조건에 따라 증가될 수 있다. 


연습 문제 

요청사항: 아래 html 텍스트에서 "https://www.hello.co.kr/companies/123/testing" 형식의 포멧에서 123, 567 의 값을 뽑아낼 수 있는 정규식을 작성하시오. 

안녕하세요 테스트입니다. <a="https://www.hello.co.kr/companies/123/testing"> 안녕하세요 테스트2 입니다. "https://www.hello.co.kr/companies/567/testing">

Hint: 시작값이 "https://www.hello.co.kr/companies/" 이고 종료값이 "/testing" 인 것을 하나의 패턴으로 인식하기 

정답

더보기
https://www.hello.co.kr/companies/([0-9]+)/testing

<참고자료>

http://www.nextree.co.kr/p4327/

https://m.blog.naver.com/PostView.nhn?blogId=rorean&logNo=221582429295&proxyReferer=https:%2F%2Fwww.google.com%2F

https://unlimitedpower.tistory.com/entry/%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%EA%B3%BC-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함