0

私はPerlスクリプトをまとめて、ディレクトリを調べ、ソース内のさまざまなキーを照合して、結果をテキストファイルに出力しました。一致操作はうまく機能しますが、最終的な目標は置換操作を実行することです。Perlスクリプトは次のとおりです。

  #!/usr/bin/perl
  #use strict;
  use warnings;

  #use File::Slurp;

  #declare variables
  my $file = '';
  my $verbose = 0;
  my $logfile;

  my @files = grep {/[.](pas|cmm|ptd|pro)$/i} glob 'C:\users\perry_m\desktop\epic_test\pascal_code\*.*';

  #iterate through the files in input directory
  foreach $file (@files) {

     print "$file\n";

     #read the file into a single string
     open FILEHANDLE, $file or die $!;
     my $string = do { local $/; <FILEHANDLE> };

     #perfrom REGEX on this string

     ########################################################
     #fix the include formats to conform to normal PASCAL
     $count = 0;
     while ($string =~ m/%INCLUDE/g)
     {
        #%include
        $count++;
     }
     if ($count > 0)
     {
        print " $count %INCLUDE\n";
     }
     $count = 0;
     while ($string =~ m/INCLUDE/g)
     {
        #%INCLUDE;
        $count++;
     }
     if ($count > 0)
     {
        print " $count INCLUDE\n";
     }
     $count = 0;
     while ($string =~ m/(%include\s+')[A-Za-z0-9]+:([A-Za-z0-9]+.[A-Za-z]+')/g)
     {
        #$1$2;
        $count++;
     }
     if ($count > 0)
     {
        print " $count XXXX:include \n";
     }        
  }

これにより、必要に応じて出力が生成されます。例を以下に示します。

  C:\users\perry_m\desktop\epic_test\pascal_code\BRTINIT.PAS
   1 INCLUDE
   2 XXXX:include 
   39 external and readonly

ただし、上記のコメント行に示されている置換操作を使用して、正規表現操作を変更して置換を実装しようとすると、スクリプトがハングし、戻らない。どういうわけかメモリに関係していると思いますが、Perlは初めてです。また、可能であればファイルを1行ずつ解析しないようにしました。

例:

  while ($string =~ s/%INCLUDE/%include/g)
  {
     #%include
     $count++;
  }

  while ($string =~ s/(%include\s+')[A-Za-z0-9]+:([A-Za-z0-9]+.[A-Za-z]+')/$1$2;/g)
  {
     #$1$2;
     $count++;
  }

編集:例を簡略化

4

2 に答える 2

4

問題はwhileループにあります。のようなループ

while ($string =~ m/INCLUDE/g) { ... }

INCLUDEターゲット文字列内の出現ごとに1回実行されますが、次のような置換

$string =~ s/INCLUDE/%INCLUDE;/

すべての交換を一度に行い、行われた交換の数を再調整します。だからループ

while ($string =~ s/INCLUDE/%INCLUDE;/g) { ... }

の前にパーセント記号を追加し、後にセミコロンを追加しますINCLUDE

行われた置換の数を見つけるには、このようなすべてのループを次のように変更します。

$count = $string =~ s/INCLUDE/%INCLUDE;/g
于 2012-10-15T19:07:21.160 に答える
0

のパターンs/INCLUDE/%INCLUDE/gは置換にも一致するため、whileループで実行している場合は、永久に実行されます(メモリが不足するまで)。

s///g1回のショットですべての一致が置き換えられるため、ループに入れる必要はほとんどありません。同じm//gことが当てはまります。リストコンテキストに配置すると、1つのステップでカウントが実行されます。

于 2012-10-15T19:06:46.200 に答える