파일내의 문자열 치환

메모리 상에 있는 문자열을 치환하는 것은 정규식(Regular Expression, RE)를 습득하신 여러분께는 누워서 떡 먹기가 된지 이미 오래인 것으로 알고 있습니다.

그런데 저는 파일에 있는 어떤 특정 문자열들을 치환하는 것에 대하여 Perl을 배우기 전부터 관심을 가지고 여러 가지 방법을 써 보았고 C++을 이용하여 만들어도 보았습니다. 왜냐하면 프로그램을 짜다보면 변수 이름을 바꾸고 싶을 때가 종종 있는데 그 경우 여러 개의 소스파일에 같은 변수 이름이 널려 있을 때는 그냥 dos의 batch 명령을 이용하면 매우 편하겠다는 생각이 들어서였습니다.

이번 것은 조금 달리 library의 개념에 대하여 살펴보면서 프로그램을 짜 봅시다요.

library는 도서관입니까 ? 프로그램을 하다보면 어떤 특별한 기능을 가진 sunroutine을 대대손손, 이 프로그램, 저 프로그램에서 공동으로 사용하고 싶은 경우가 자주 있습니다. 만일 이러한 subroutine을 사용하는 프로그램마다 모두 한 쪽 구석에 베껴 놓아야 한다면 아주 불편하겠지요. 그런 불평이 혹 생길까봐 Perl언어 역시 라이브러리를 만들어 쓸 수 있게 설계되었습니다.

라이브러리로 쓰이는 Perl 소스파일은 대개 이렇게 생겼습니다.

# library.pl

sub sub1
{
  print "This is sub1.\n";
}

sub sub2
{
  print "This is sub2.\n";
}

# 몇 개의 subroutine도 좋습니다.

1;  # 뭔가 참 값을 리턴해야 합니다.
그러면 여러 프로그램들에서 sub1, sub2를 부를 때 이렇게 합니다.
# prog1.pl

require 'library.pl';  # library.pl에 담긴 subroutine을 쓰려면 미리
                       # 요청을 해야합니다. 안 그러면 혼납니다.
print "Calling subroutines from prog1 !\n";
&sub1;
&sub2;

# prog2.pl

require 'library.pl';  # 요청을 합니다.

print "Calling subroutines from prog2 !\n";
sub1(); # &sub1 대신 이렇게도.
sub2();
문서 파일 내에 있는 어떤 특정 패턴의 문자열, 구문 등을 다른 문자열로 치환하기 위한 프로그램을 아래처럼 만들어 보았습니다. 당연히 실험을 거쳤기 때문에 안전하다고 볼 수 있지만 여타 기능의 추가나 안전장치의 보강 등을 위해서 조금 고쳐보시는 것도 공부에 보탬이 될 겁니다.

아래에 있는 tempnam.pl은 임시파일의 이름을 만들어내는 subroutine을 포함하고 있습니다. 임시파일의 이름을 만들어야하는 상황은 여러 가지가 있을 수 있습니다. 그 상황은 여러분이 프로그램을 하시다 보면 자주 부딪히게 될 테니 따로 언급은 하지 않겠습니다. 이 tempnam.pl은 라이브러리로 활용될 수 있습니다. 어떤 프로그램에서도 require한 후에 그 안에 있는 tempName subroutine을 불러 쓸 수 있습니다.

이 subroutine은 문자열 '0000'에서 '9999'까지 0000, 0001, 0002, ... 9998, 9999 등에 대하여 temp0000.gr, temp0001.gr처럼 앞에는 'temp', 뒤에는 '.gr'을 붙여서 하나의 파일 이름을 만들어 낸 다음 그 파일이 혹시 존재하는지, 또는 디렉토리 이름은 아닌지 검사해 봅니다. 만일 그런 경우에는 다음 문자열로 넘어가서 다시 실험하고, 그렇지 않은 경우에는 그 이름을 임시파일 이름으로 지정하여 리턴해 줍니다. 만일 temp9999.gr까지 다 검사한 후에도 임시파일 이름을 만들 수 없다면 "\n"를 리턴 함으로써 임시파일명을 만드는데 실패하였음을 알려줍니다.

# tempnam.pl

sub tempName {
  local( $tn ) = "\n";  # local 변수를 선언합니다.
  local( $temp );       # 혹시 다른 프로그램에서 같은 이름을 쓸지도
                        # 모르니까요.
  for( '0000'..'9999' )
  {
    $temp = 'tmp'.$_.'.gr';
    if( !(-d $temp) && !(-e $temp) )  # $temp가 존재하는 파일 이름이나
    {                                 # 디렉토리 이름이 아니라면,
      $tn = $temp;                    # return할 변수에 저장한 후
      last;                           # for loop에서 빠져나갑니다.
    }
  }
  return $tn;
}

1;   # 뭔가를 리턴해야 합니다. 그렇지 않으면 tempnam.pl은 정당한 프로그램이
     # 될 수 없기 때문이지요.
last의 쓰임새가 저 위에 있었군요. 아주 편리한 기능이지요 ?

여기까지 Perl 이야기 5편을 마쳤습니다.


이전 | 목록 | 다음
Comments