[첫화면으로]"Perl/문자열나누기" 페이지의 변경 내역

마지막으로 [b]


현재 버전 . . . . (수정) 2012-2-11 12:25 am 수정한 사람: Raymundo
15 번째 수정본 . . . . 2011-12-30 12:16 am 수정한 사람: Raymundo
 

변경사항 (가장 최근의 "일반적인 수정"부터) (소소한 수정)

-17,10 +17,107
=== # split에 lookaround를 사용하여 특수한 경우가 생기지 않게 하라 ===
* 원문: [http://www.effectiveperlprogramming.com/blog/1411 Use lookarounds to split to avoid special cases | The Effective Perler]
* 번역, 요약
* 원문의 테스트 코드를, 출력 결과를 알아보기 쉽도록 수정을 했음
구분자가 단일 캐릭터일 때. 쉽다.
{{{#!vim perl
use v5.10;
my @letters = split /:/, 'a:b:c:d:e';
say join(":", @letters);
}}}
{{{#!vim
a:b:c:d:e
}}}
구분자 패턴의 길이가 2이상이거나 가변적일 때도, 무난하다.
{{{#!vim perl
my @cats = split /\s+/, 'Buster
Mimi     Roscoe';
say join(":", @cats);
}}}
{{{#!vim
Buster:Mimi:Roscoe
}}}
구분자가 좌우대칭인 형태, 즉 각 값의 시작과 끝을 표시하는 마크가 있는 상황이라면 좀 복잡해진다. 값들 사이에 있는 패턴을 가지고 쪼갤 경우 첫번째 값의 앞과 마지막 값의 뒤에 있는 게 지워지지 않는다.
{{{#!vim perl
my @cats = split /></, '<Buster><Mimi><Roscoe>';
say join(":", @cats);
}}}
{{{#!vim
<Buster:Mimi:Roscoe>
}}}
이렇게 남은 것은 <code>split</code>한 후에 따로 처리하고자 할 수도 있다:
{{{#!vim perl
my @cats = split /></, '<Buster><Mimi><Roscoe>';
$cats[0] =~ s/<//;
$cats[-1] =~ s/>//;
say join(":", @cats);
}}}
물론 이렇게 해도 동작은 하지만, 이렇게 따로 처리해야 하는 특별한 경우를 만들지 않는 것이 좋다.
제거하려는 캐릭터들 모두에 매치되도록 구분자를 지정할 경우, 한가지 문제가 생긴다. 제일 앞에 있는 구분자 앞쪽에 빈 스트링 하나가 첫번째 원소가 된다: (출력 부분에 <code>buster</code> 앞에 콜론이 붙은 것에 유의)
{{{#!vim perl
my @cats = split /><|\A<|>\z/, '<buster><mimi><roscoe>';
say join(":", @cats);
}}}
{{{#!vim
:buster:mimi:roscoe
}}}
첫번째 필드를 쉬프트시켜서 제거할 수 있으나, 역시 보기 좋지 않다:
{{{#!vim perl
my @cats = split /><|\A<|>\z/, '<buster><mimi><roscoe>';
shift @cats;
say join(":", @cats);
}}}
캐릭터들을 매치시키는 게 아니라, lookaround를 사용하여 이런 좌우대칭 형태 구분자의 사이에서 split을 하게 할 수 있다. lookaround는 스트링 내의 특정한 조건에 매치가 되며 캐릭터를 소모하지 않는다<footnote(즉 현재 검사하는 위치를 가리키는 포인터가 이동하지 않고 그 자리에 유지된다)>.
lookbehind와 lookahead<footnote(더 자세한 것은 [[/정규표현식]] 참조)>를 나란히 사용하여, 두 조건이 동시에 매치되는 지점에서 스트링을 쪼갤 수 있다.
{{{#!vim perl
my @cats = split /(?<=>)(?=<)/, '<buster><mimi><roscoe>';
say join(":", @cats);
}}}
{{{#!vim
<buster>:<mimi>:<roscoe>
}}}
위 출력결과에서는, 구분자 캐릭터들이 없어지지는 않았으나, 이제 각 원소들을 동일하게 처리하면 되며 특별히 처리할 케이스가 없다.
{{{#!vim perl
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);
}}}
{{{#!vim
buster:mimi:roscoe
}}}
좀 더 복잡하게, 각 필드가 따옴표로 둘러쌓여 있고, 다시 쉼표로 구분되어 있는 경우:
{{{#!vim perl
my @cats =
    map { my $s = $_; $s =~ s/\A"|"\z//g; $s }
split /(?<="),(?=")/,
'"Buster","Mimi","Roscoe"';
say join(":", @cats);
}}}
쉼표와 따옴표를 한번에 제거할 수 있는 더 복잡한 정규표현식을 만들 수도 있겠지만, 지금처럼 단순한 단계 두 번을 거치는 것에 비해, 코드를 읽고 유지하기에 어려울 것이다.
요점:
* 구분자를 한 번에 제거할 필요는 없다
* lookbehind와 lookahead를 나란히 사용하여 스트링 내에 특정한 위치를 지정할 수 있다

-104,7 +201,7
<div class="comments">
<longcomments(100)>
----
<trackbackreceived>
</div>
----
[[컴퓨터분류]]