コンバータ的なもの

テキストファイル内に含まれるキーワードを別の文字列で置換するプログラム。

  • キーワードと置換後文字列は設定ファイル(YAML形式)で指定
  • 設定ファイル名はプログラム名の拡張子を『.yaml』にしたもの
  • 置換後文字列はファイル指定が可能(ファイルの内容で置換される)
  • ファイル指定の内容にキーワードが含まれている場合、そのキーワードも置換される
use strict;
use warnings;
use YAML;

################################################
# main
my $ini = YAML::LoadFile(makeInifile());
my $target = shift(@ARGV);
my $lines = readFile($target);
convert($lines, $ini);
writeFile(makeConvertedFilename($target), $lines);


################################################
# common sub routine
sub readFile{
  my ($filename) = @_;
  
  open(IN, $filename) or return undef;
  my @lines = <IN>;
  close(IN);
  
  chomp(@lines);
  return wantarray ? @lines : \@lines;
}

sub writeFile{
  my ($filename, $lines) = @_;
  $lines = [ $lines ] unless(ref($lines));
  
  open(OUT, "> $filename") or die("error : invalid file, $filename");
  for my $line (@$lines){
    print OUT $line . "\n";
  }
  close(OUT);
}

sub cat{
  my ($lines) = @_;
  $lines = [ $lines ] unless(ref($lines));
  
  my $cated;
  for my $line (@$lines){
    $cated .= $line ."\n";
  }
  return $cated;
}

################################################
# convert
sub makeConvertedFilename{
  my ($basename) = @_;
  return $basename . "_converted.txt";
}

sub makeKeyword{
  my ($key) = @_;
  return "@" . $key . "@";
}

sub convertByFile{
  my ($lines, $fileIni) = @_;
  $lines = [ $lines ] unless(ref($lines));
  
  my $cnt = 0;
  for my $line (@$lines){
    while(my ($key, $value) = each %$fileIni){
      my $keyword = makeKeyword($key);
      if($line !~ /$keyword/){
        next;
      }
      
      my $valueLines = readFile($value);
      unless(defined($valueLines)){
        next;
      }
      my $valueData = cat($valueLines);
      $line =~ s/$keyword/$valueData/g;
      $cnt++;
    }
  }
  
  if($cnt != 0){
    convertByFile($lines, $fileIni);
  }
}

sub convertByValue{
  my ($lines, $valueIni) = @_;
  $lines = [ $lines ] unless(ref($lines));
  for my $line (@$lines){
    while(my ($key, $value) = each %$valueIni){
      my $keyword = makeKeyword($key);
      $line =~ s/$keyword/$value/g;
    }
  }
}

sub convert{
  my ($lines, $ini) = @_;
  $lines = [ $lines ] unless(ref($lines));
  
  convertByFile($lines, $ini->{file});
  convertByValue($lines, $ini->{value});
}


################################################
# ini file
sub makeInifile{
  my $tmp = $0;
  $tmp =~ s/\.pl$/.yaml/g;
  return $tmp;
}

catの処理はもっと単純なやり方がある気がするが、思いつかなかった、、、。

下は設定ファイル例。キーワードと文字列の対応は「value」のマップ、キーワードとファイル指定の場合は「file」のマップを利用。

value : 
 KEYWORD1 : ムムムムム!
 KEYWORD2 : ヌヌヌヌヌ!
 KEYWORD3 : そんなばかな!
 KEYWORD4 : それはそれでよし!

file :
 KEYWORD5 : C:\converter\test.txt
 KEYWORD6 : C:\converter\template.txt