@변수 = split( / 구분자 /, $변수);
@변수 = split( / (구분자) /, $변수);
구분자가 단일 캐릭터일 때. 쉽다.
use v5.10; my @letters = split /:/, 'a:b:c:d:e'; say join(":", @letters);
a:b:c:d:e
구분자 패턴의 길이가 2이상이거나 가변적일 때도, 무난하다.
my @cats = split /\s+/, 'Buster Mimi Roscoe'; say join(":", @cats);
Buster:Mimi:Roscoe
구분자가 좌우대칭인 형태, 즉 각 값의 시작과 끝을 표시하는 마크가 있는 상황이라면 좀 복잡해진다. 값들 사이에 있는 패턴을 가지고 쪼갤 경우 첫번째 값의 앞과 마지막 값의 뒤에 있는 게 지워지지 않는다.
my @cats = split /></, '<Buster><Mimi><Roscoe>'; say join(":", @cats);
<Buster:Mimi:Roscoe>
이렇게 남은 것은 split
한 후에 따로 처리하고자 할 수도 있다:
my @cats = split /></, '<Buster><Mimi><Roscoe>'; $cats[0] =~ s/<//; $cats[-1] =~ s/>//; say join(":", @cats);
물론 이렇게 해도 동작은 하지만, 이렇게 따로 처리해야 하는 특별한 경우를 만들지 않는 것이 좋다.
제거하려는 캐릭터들 모두에 매치되도록 구분자를 지정할 경우, 한가지 문제가 생긴다. 제일 앞에 있는 구분자 앞쪽에 빈 스트링 하나가 첫번째 원소가 된다: (출력 부분에 buster
앞에 콜론이 붙은 것에 유의)
my @cats = split /><|\A<|>\z/, '<buster><mimi><roscoe>'; say join(":", @cats);
:buster:mimi:roscoe
첫번째 필드를 쉬프트시켜서 제거할 수 있으나, 역시 보기 좋지 않다:
my @cats = split /><|\A<|>\z/, '<buster><mimi><roscoe>'; shift @cats; say join(":", @cats);
캐릭터들을 매치시키는 게 아니라, lookaround를 사용하여 이런 좌우대칭 형태 구분자의 사이에서 split을 하게 할 수 있다. lookaround는 스트링 내의 특정한 조건에 매치가 되며 캐릭터를 소모하지 않는다1.
lookbehind와 lookahead2를 나란히 사용하여, 두 조건이 동시에 매치되는 지점에서 스트링을 쪼갤 수 있다.
my @cats = split /(?<=>)(?=<)/, '<buster><mimi><roscoe>'; say join(":", @cats);
<buster>:<mimi>:<roscoe>위 출력결과에서는, 구분자 캐릭터들이 없어지지는 않았으나, 이제 각 원소들을 동일하게 처리하면 되며 특별히 처리할 케이스가 없다.
my @cats = # map { s/\A<|>\z//rg } # Perl 5.14 부터는 /r 옵션을 써서 이렇게도 가능 map { my $s = $_; $s =~ s/\A<|>\z//g; $s } split /(?<=>)(?=<)/, '<buster><mimi><roscoe>'; say join(":", @cats);
buster:mimi:roscoe
좀 더 복잡하게, 각 필드가 따옴표로 둘러쌓여 있고, 다시 쉼표로 구분되어 있는 경우:
my @cats = map { my $s = $_; $s =~ s/\A"|"\z//g; $s } split /(?<="),(?=")/, '"Buster","Mimi","Roscoe"'; say join(":", @cats);
쉼표와 따옴표를 한번에 제거할 수 있는 더 복잡한 정규표현식을 만들 수도 있겠지만, 지금처럼 단순한 단계 두 번을 거치는 것에 비해, 코드를 읽고 유지하기에 어려울 것이다.
요점:
split 에 구분자로 주어지는 패턴이 다음과 같은 경우는 특별하게 동작한다:
//
은 문자열을 캐릭터들로 쪼갠다.
?
, *
, lookaround 등을 사용한)도 문자열을 캐릭터들로 쪼갠다.
' '
또는 " "
는 공백을 기준으로 문자열을 분리하되, 제일 앞에 있는 빈 필드는 버린다.
/^/
는 문자열을 라인 단위로 쪼갠다. (정확히 이 형태일 때만 그렇고, /^(?=.)/
와 같이 패턴에 다른 게 섞인다면 - 설령 제대로 매치되더라도 - 동작하지 않는다. 이 때는 패턴에 /m
플래그를 붙여주어야 한다)
my $str = ' Buster and Mimi'; print join(":", split //, $str); # 빈 패턴 # : :B:u:s:t:e:r: :a:n:d: :M:i:m:i print join(":", split /z*/, $str); # 빈 스트링 # : :B:u:s:t:e:r: :a:n:d: :M:i:m:i print join(":", split / /, $str); # 일반적인 공백 패턴 # ::Buster:and:Mimi # 앞에 ""가 두 번 들어감 print join(":", split ' ', $str); # 따옴표로 둘러싼 단일 공백의 경우 # Buster:and:Mimi # 앞에 두 개의 ""가 없어짐 $str = "Line 1\nLine 2\nLine 3"; print join(":", split /^/, $str); # Line 1 # :Line 2 # :Line 3
2007년에 끙끙댔던 문제인데, 막상 답을 알고 나니 매우 간단해져서, 과거 내용은 삭제함
# 이 파일은 cp949로 저장되어 있음 use Encode; my $str = decode("cp949", "English와 한글"); my $length = length($str); for (my $i = 1; $i < $length; $i++) { printf "%2d : ", $i; print "[", encode("cp949", substr($str, 0, $i)), "] [", encode("cp949", substr($str, $i)), "]\n"; }
1 : [E] [nglish와 한글] 2 : [En] [glish와 한글] 3 : [Eng] [lish와 한글] 4 : [Engl] [ish와 한글] 5 : [Engli] [sh와 한글] 6 : [Englis] [h와 한글] 7 : [English] [와 한글] 8 : [English와] [ 한글] 9 : [English와 ] [한글] 10 : [English와 한] [글]