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 的新手。如果可能的话,我还试图避免逐行解析文件。

例子:

  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目标字符串中的每次出现执行一次,但是像

$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///g将一次性替换所有匹配项,因此您很少需要将其放入循环中。也一样m//g,如果你把它放在列表上下文中,它会一步完成计数。

于 2012-10-15T19:06:46.200 回答