2012년 8월 1일 수요일

[Perl programming #2] substr() 함수 알뜰하게 사용하기

스트링 형태로 저장된 염기 혹은 단백질 서열을 60 문자마다 깨끗하게 줄바꿈을 하여 FASTA format으로 출력할 일이 아주 많다. BioPerl을 쓰면 되지만, 일부러 sequence object를 선언하여 쓰기에는 너무 번거롭다. 그동안 내가 사용한 코드는 스트링을 낱자로 하나하나 분해하여(split() 사용) 60개가 맞는지 센 다음에 출력하는, 그야말로 원시적인 것이었다. 작동하는데는 문제가 없으나, 여기에 공개하기에는 너무나 부끄러운 코드이다. 어제 Python 교육을 받으면서 머리를 스쳐가는 것이 있어서 다음과 같이 응용해 보았다.

$orig = 'AGCTAGGC...';
while ($orig) {
    print substr $orig, 0, $width;
    print "\n";
    $orig = substr $orig, $width;
}

대단히 간결하고 명확하지 않은가? while 구문을 이렇게 활용할 수 있을 것으로는 생각하지 못했다. 짧고, 읽기 쉽고, 능률적인 코딩 습관은 항상 추구해야 할 바라고 생각한다. 물론 한 가지의 목적을 달성하기 위하여 여러가지 해법이 있을 수 있다는 것인 Perl의 철학이지만, 조금만 생각을 더 하고 궁리를 해 보면 훨씬 능률적인 작업을 할 수 있음을 알아야 한다.

substr() 함수의 다양한 사용법은 여기에서...

http://perldoc.perl.org/functions/substr.html

아직 다 끝난 것이 아니다. substr()는 lvalue로 쓸 수 있다는 것. 이는 등호(=)의 왼쪽에 올 수 있음을 의미하는 것이다. 일반적인 함수라면 반환된 값을 내어 놓고, 이를 등호 왼쪽에 오는 변수에 저장하게 된다. substr()도 마찬가지이다. 인수로 주어진 스트링 내부의 지정된 부분을 끊어서 왼쪽의 변수에 자정하는 것이다.

$var = my_func(..)

substr()를 등호 왼쪽에 쓰게 되면, 얘기가 달라진다. substr()을 예로 든다면, 인수로 지정된 변수 내의 특정 위치를 오른쪽 변수에 저장된 값으로 바꿔친다는 것이다. 위에서 보인 샘플 코드를 더욱 단순하게 만들 여지가 있다는 것이다.

그런데 아무리 궁리를 해도 답이 안나온다^^ 위의 코드가 가장 간단한 코드일지도 모르겠다.

댓글 2개:

aero's blog :

원래 스트링을 계속적으로 수정,대입하면서 작업하면 새로 메모리를 확보해야기 때문에 비교적 비용이 많이듭니다.
use warnings 프래그마를 쓰면 위코드는 substr outside of string at 같은 경고메시지도나오고요. substr을 쓰면서도 줄이려면

while ($orig) {
print( substr($orig, 0, $width, ''), "\n");
}

처럼 하시면 됩니다.

정규식을 쓰면

foreach ($orig2 =~ m/.{1,$width}/g) {
print "$_\n";
}

처럼 할 수도 있습니다.

jeong0449 :

제 블로그에 이렇게 값진 코멘트를 남기는 분이 계실 것으로는 생각하지 못했습니다. 감사합니다^^