簡體   English   中英

Perl正則表達式匹配有效,但替換無效

[英]Perl Regex match works, but replace does not

我整理了一個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++;
  }

編輯:簡化示例

問題出在您的while循環上。 像這樣的循環

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

將針對目標字符串中每次出現INCLUDE都執行一次,但是類似

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

將一次性完成所有替換,並重新獲取替換的數量。 如此循環

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

在每一個INCLUDE之前和分號后面都會不斷添加越來越多的百分號。

要查找更換的數量,請將所有循環更改為

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

s/INCLUDE/%INCLUDE/g中的模式也將與替換匹配,因此,如果您在while循環中運行它,它將永遠運行(直到內存不足)。

s///g可以一次性替換所有比賽,因此您很少需要將其放在循環中。 m//g也一樣,如果將其放在列表上下文中,它將一步完成計數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM