본문 바로가기

별걸다하는 IT/프로그래밍언어

[JAVA 자바] String클래스의 split 메서드로 문자열 분리하는 법. 문자열 파싱. StringTokenizer, substring와 차이?

안녕하세요 양햄찌 블로그 입니다.

저번 시간에는 String클래스의 substring에 대해 알아보았는데요,

요 아이는 인덱스를 기준으로 문자열을 추출하는 메서드였죠 ㅎㅎ

 

저번 포스팅이 궁금하신 분은 아래 링크를 참고해주세요.

▼자바 substring 사용법: jhnyang.tistory.com/335

 

[JAVA 자바] substring 특정 위치부터 특정 위치까지 문자열 파싱하는 법, 문자열 위치(인덱스)로 문��

안녕하세요 양햄찌 블로그입니다. 오늘은 요청을 받아 오랜만에 자바에 대한 포스팅을 작성해보려고 합니다. 오늘 주제는~~ 문자열 파싱하는 법, 문자열 자르는 방법 알아보기 첫번째 포스팅입�

jhnyang.tistory.com

문자열 파싱하는 법 문자열 자르는 법 알아보기

오늘은 저번 포스팅에 이어서 

문자열 파싱에 쓰이는 split와 StringTokenizer에 대해 살펴보려고 합니다.

split작성하다가 길어질 것 같으면 다음 포스팅에 StringTokenizer에 대해 이어서 작성해보도록 할게요.

문자열 파싱법

 몇번째부터 몇번째까지~ 이런식으로 위치에 해당하는 부분을 문자열로 잘라서 뽑아내고 싶으면 String 클래스의 substring을 사용하면 됩니다.

 구분자가 중간 중간 있어, 구분자를 기준으로 문자열을 토막내고 싶을 경우, String클래스의 split 메서드나 StringTokenizer클래스를 사용하시면 돼요. 

◆이 외에도 Scanner의 useDelimiter를 이용할 수도 있습니다.

String의 split 메서드 문법 SYNTAX

split 메서드는 String에서 제공하는 메서드입니다.

split 메서드 또한 오버로딩 되어있습니다. 

매개변수가 1개인 split가 있고 2개인 split가 있네요.

각각 어떻게 사용하는지 알아봅시다. 

split메서드의 리턴타입은 문자열 배열입니다. (String[])

 

split (String regex)는 문자열을 정규식에 맞춰서 분리합니다.

split (String regex, int limit)는 똑같이 문자열을 정규식에 맞춰서 분리하는데 limit만큼 문자열을 자르는거예요. 

만약 두 번째 인자로 2가 들어갔다면, 잘린 문자열의 개수가 2개가 될때까지만 자르는거죠.

 

실패시 PatternSyntaxException 익셉션을 발생시킵니다. 

기본 사용법 HOW TO USE SPLIT

[구분자로 문자열 분리하기]

기본 split메서드를 사용하여 문자열을 @ 구분자를 이용해 분리해봅시다.

public class Main {
	public static void main(String[] args) {
		String str = "jhnyang@tistory@com"; 
		String[] strAry = str.split("@"); 
	  
		for (String s : strAry) 
			System.out.println(s); 
	}
}

str문자열에 총 @가 두개 들어가있으니 strAry는 세개로 분리되었을 거예요. 반복문으로 하나하나씩 출력해서 잘 파싱됐는지 확인해봅시다.

잘 파싱되었네요.

 

[메타 문자 구분자로 사용하기]

그럼 점(.)으로 구분하고 싶으면 어떻게 해야할까요?

public class Main {
	public static void main(String[] args) {
		String str = "jhnyang.tistory.com"; 
		String[] strAry = str.split(".");  //-->잘못된 사용예
	  
		for (String s : strAry) 
			System.out.println(s); 
	}
}

실제로 위와 같이 작성하고 출력해보면 결과가 아무것도 없는 것을 확인할 수 있습니다.

split는 정규표현식으로 문자를 분리하는데요. 정규표현식에서 점(.)은 하나의 문자와 대응하는 일종의 메타문자이기 때문입니다. 

public class Main {
	public static void main(String[] args) {
		String str = "jhnyang.tistory.com"; 
		String[] strAry = str.split("\\."); 
	  
		for (String s : strAry) 
			System.out.println(s); 
	}
}

메타문자가 아닌 문자 그대로 특수문자를 구분자로 사용하고 싶을 경우에는 이스케이프 문자인 "\\"를 앞에 붙여줘야 해요. 그래야 위처럼 결과가 제대로 파싱됩니다. 

 

[빈 문자열을 하나의 문자열로 인식하는가]

split의 경우 정규식으로 문자열을 분리하였을 때, 빈 문자열이 결과로 있다면 이를 하나의 문자열로 취급합니다.

public class Main {
	public static void main(String[] args) {
		String ipv6 = "fe80::bda7:2e2:a235:8f98"; 
		String[] octets = ipv6.split(":"); 
	  
		for (int cnt =1; cnt<= octets.length; cnt++ ) 
			System.out.println(cnt + "번째옥탯:" + octets[cnt-1]); 
	}
}

 

IPv6를 ':'로 분리해봤어요.

빈 문자열도 결과에 들어간 것을 확인할 수 있습니다.

 

[리턴 타입을 배열로 받기 싫을 때]

배열로 통째로 리턴받아서 for문을 이용해 다 꺼낼 필요 없이, 특정 위치 부분을 바로 문자열에 저장해 접근하고 싶을 수 있어요.

전화번호에서 지역번호 부분만 파싱해, 문자열에 저장하는 예제를 통해 사용법을 익혀봅시다.

public class Main {
	public static void main(String[] args) {
		String tel = "02-123-4567"; 
		String area_nbr = tel.split("-")[0]; 
	    System.out.println(area_nbr);
	}
}

전화번호니까 "-"로 구분해줬어요. 그리고 첫 번째 값을 area_nbr에 넣어 바로 출력해줬습니다.

 

[구분자를 여러개 두고 싶을 때]

split는 정규식을 받기 때문에 당연히 구분자를 여러개 둘 수 있습니다.

public class Main {
	public static void main(String[] args) {
		String mail = "hello-kitty@hellokitty.com"; 
		String[] strAry = mail.split("-|@|\\."); 
		
		for (String s : strAry) 
			System.out.println(s); 
	}
}

이메일을 '-', '@', '.' 세가지 구분자가 보이면 파싱하도록 작성해봤어요.

점(.)앞에 \\가 붙는건 메타문자를 특수문자 취급해주기 위한 것임은 위에서 확인했었어요~

 

[limit 사용법]

이번에는 간단히 limit를 사용해봄으로써 결과를 비교해봅시다.

public class Main {
	public static void main(String[] args) {
		String str = "123::4:67:10::::"; 
		String[] noLimit = str.split(":"); 
		String[] limitTwo = str.split(":", 2); 
		String[] limitPlus = str.split(":", 7); 
		String[] limitZero = str.split(":", 0); 
		String[] limitMinus = str.split(":", -1); 
		
		System.out.println("-----noLimit-----");
		for (int cnt =0; cnt< noLimit.length; cnt++ ) 
			System.out.println(cnt + "위치:" + noLimit[cnt]); 
		
		System.out.println("-----limitTwo-----");
		for (int cnt =0; cnt< limitTwo.length; cnt++ ) 
			System.out.println(cnt + "위치:" + limitTwo[cnt]); 
		
		System.out.println("-----limitPlus-----");
		for (int cnt =0; cnt< limitPlus.length; cnt++ ) 
			System.out.println(cnt + "위치:" + limitPlus[cnt]); 
		
		System.out.println("-----limitZero-----");
		for (int cnt =0; cnt< limitZero.length; cnt++ ) 
			System.out.println(cnt + "위치:" + limitZero[cnt]); 
		
		System.out.println("-----limitMinus-----");
		for (int cnt =0; cnt< limitMinus.length; cnt++ ) 
			System.out.println(cnt + "위치:" + limitMinus[cnt]); 
	}
}

 

결과를 먼저 봅시다!

빨간색 박스부분! - split(String regex)와, split (String regex, 0)일 경우!

맨 처음 리미트 없이 하나의 인자만 넣어줬을 때와 limit 값이 0일 때의 결과가 동일한 것을 확인할 수 있습니다.

즉 두번째 매개변수 limit의 디폴트 값은 0입니다.

 

limit값이 0일 경우에는 문자열이 구분자로 구분이 되었어도 맨 뒤의 값들이 다 빈 문자열이면 이를 무시합니다.

보면 결과 인덱스가 4까지만 있죠?! 배열 중간 중간 빈 문자열이 껴있는 것은 토큰으로 인식하지만 마지막이 빈문자열인 것들은 무시해요.

limit에다가 인자로 2를 넣어줬더니 문자열을 두개로 분리하고 더 이상 구분자를 기준으로 나누지 않은 것을 확인할 수 있습니다. 뒤에 결과가 없어도 분리가 된 이상 limit개수만큼 리턴해줬어요.

 

limitPlus부분에서 확인할 수 있듯이

리미트가 양수일 경우에는 뒤에 구분결과가 빈문자열이여도 그 리미트 개수만큼 다 쳐서 리턴해줍니다.

limt로 7을 넣어줬더니 0부터 6까지 총 7개 원소를 가진 문자열배열을 리턴해줬어요.

limit에 양수값을 넣어줬을 때에는 문자열을 limit개수만큼 분리해줍니다.

 

반면 마이너스이면 처음부터 끝까지 결과가 빈문자열인 것까지 다 포함한 파싱 결과를 리턴해줍니다.

StringTokenizer와 차이?

다음 시간에는 StringTokenizer에 대해 진행해볼텐데요,

둘 다 모두 문자열 파싱하는데 사용할 수 있습니다.

선행학습(?)으로 간단한 차이만 짚고 넘어가보도록 할게요.

 

■ 먼저 가장 큰 차이점은 split는 String클래스에 속해있는 메소드이고 StringTokenizer는 java.util에 포함되어 있는 클래스입니다.

 split는 정규표현식으로 구분하고 StringTokenizer는 문자로 구분합니다.

 앞에서 확인했듯이 split는 빈문자열을 토큰으로 인식하는 반면 StringTokenizer는 빈 문자열을 토큰으로 인식하지 않는 차이점도 있어요.

 split는 결과 값이 문자열 배열이지만, stringtokenizer는 문자열입니다. (반복문으로 계속 이어서 분리해서 반환하는거)

 배열에 담아 반환하는 스플리트는 데이터를 바로바로 잘라서 반환해주는 스트링토크나이져보다 성능이 약간 뒤쳐지겠죠? 그러나 데이터양이 많은 경우 거기서 거기기 때문에 크게 신경쓸 필요는 없습니다.

 

오늘은 간단하게 split 메서드에 대해 알아봤어요 :)

공감은 정보공유를 널리 이롭게 하는데 큰 힘이 됩니다. 오늘도 수고하셨어요 다음 포스팅에서 봐요~!