【问题标题】:Delete lines in a file, after pattern is found in perl在 perl 中找到模式后删除文件中的行
【发布时间】:2014-11-09 02:35:16
【问题描述】:

示例输入tcl文件内容:

# Bind
 ::d::autoBindmap $intfcName 

-------------so many other lines------------------------------
############ Power information for vss #####################
#----------------------------
 #pg_vss s100
#----------------------------
 #Add pg_vss_dl interface
set  intfcName pg_vss 1.0 s 100

 #Add Verilog port binding for vss
 ::d::autoBindmap $module pg_vss $intfcName
{
 VSSGND vss_dl;
 }

############ Power information for vdd #####################
#----------------------------
 #pg_vdd s100
#----------------------------
 #Add pg_vdd_dl interface
set  intfcName pg_vdd 1.0 s 100

 #Add Verilog port binding for vss
 ::d::autoBindmap $module pg_vdd $intfcName
{
 VDD vss_dl;
 }

-----------------------so many other lines-------------------------------

 #write component 
 ::d::writeLib $module

目的: 我有一个由字符串组成的数组(由此处未提供的其他代码部分生成)。不同文件的数组内容正在发生变化。如果使用模式匹配在文件的特定行中找到任何数组元素,我需要从文件中删除之后的 11 行以及该行本身。

问题: 此更改应在当前文件本身中进行。所以,我尝试以读写模式打开文件。但是,我看到正在打印垃圾。

例如(参见上面的输入 tcl 文件):

在找到“$rpow 的电源信息”(例如 $rpow 是 vss)之后,我需要删除所有行(在本例中为 11 行)直到“}”,并删除行本身,其中 vss 是一个元素我的 remove_power_list 数组。应该对所有数组元素进行这种删除。

请问有人能解决这个问题吗?

这里只展示有问题的代码:

#####Used help of StackOverflow member Praveen to come up with this code

my $rpow;

for $rpow (@remove_power_list) {

        my $bf_content;
        open $bf_content, '+<', $bf_bind;

           my $count = 0;

        while (<$bf_content>){

                  if($_ =~ /Power\s+information\s+for\s+$rpow\s+/) {
                $count = $. + 11; 
                }   

                else    
         {   
        if($count != 0 && $. < $count)
          {   

            }   
        elsif($count != 0 && $. == $count)
          {   
             $count =0; 
              }   
         else
          {   
             print $bf_content $_; 
              }   
         }

        }             
close $bf_content;
}

注意:我无法安装 cpan File::Slurp。

预期的示例输出:

 # Bind
 ::d::autoBindmap $intfcName 

-------------so many other lines------------------------------

############ Power information for vdd #####################
#----------------------------
 #pg_vdd s100
#----------------------------
 #Add pg_vdd_dl interface
set  intfcName pg_vdd 1.0 s 100

 #Add Verilog port binding for vss
 ::d::autoBindmap $module pg_vdd $intfcName
{
 VDD vss_dl;
 }

-----------------------so many other lines-------------------------------

【问题讨论】:

  • 您的脚本有一些明显的问题。我看到的最大的一个是你不断地在你的 for 循环中重新打开 $outfile ,并且处于重写模式,这意味着你最多会在输出文件中拥有最后一行输出。但是您没有告诉我们您遇到了什么具体问题,因此很难解决您的问题。
  • @Flimzy,问题是我无法使用我正在使用的模式匹配和数组循环技术删除文件的所有内容。此外,正如您所提到的,当我尝试按照 Praveen 的建议删除固定数量的行时,我看到所有最后一行都被截断。所以,让我在这里改写我的问题:我需要根据与 remove_power_list 数组元素的匹配从输入 tcl 文件中删除行。在找到“$p 的电源信息”后,我需要删除 11 行。 $p 可以是任何东西。如果 remove_power_list 有,那么我需要删除 11 行和那一行。
  • @Flimzy:例如(参见上面的输入 tcl 文件):我需要删除所有行(在本例中为 11 行)直到“$rpow 的电源信息”之后的“}”(例如$rpow is vss) 被找到,行本身被删除。 “vss”是我的 remove_power_list 数组的一个元素。这种删除应该发生在所有数组元素上。所以,我别无选择,只能在数组的“for循环”中以读/写模式打开和关闭文件。它在文件中打印垃圾,同时写入。我正在使用用户 Pradeep 的代码,并进行了一些修改。
  • @Flimzy :我已经编辑了原始问题。希望现在有意义。
  • @aa_electronics 你的问题还不清楚。您一直说“11 行”,但您尝试删除的块似乎是可变长度的。如果您只是添加了您尝试使用脚本生成的确切输出的示例,问题会更清楚。

标签: perl file-io


【解决方案1】:

@aa_electronics:我相信你的剧本有很多问题。因此,根据您的要求,我编写了一个 perl 代码。看看吧:

输入文件: (input.txt)

 # Bind
     ::d::autoBindmap $intfcName 


    ############ Power information for vss #####################
    #----------------------------
     #pg_vss s100
    #----------------------------
     #Add pg_vss_dl interface
    set  intfcName pg_vss 1.0 s 100

     #Add Verilog port binding for vss
     ::d::autoBindmap $module pg_vss $intfcName
    {
     VSSGND vss_dl;
     }

    ############ Power information for vdd #####################
    #----------------------------
     #pg_vdd s100
    #----------------------------
     #Add pg_vdd_dl interface
    set  intfcName pg_vdd 1.0 s 100

     #Add Verilog port binding for vss
     ::d::autoBindmap $module pg_vdd $intfcName
    {
     VDD vss_dl;
     }


     #write component 
     ::d::writeLib $module

代码:

use strict;
use warnings;   

my $infile = $ARGV[0];
my $outfile = "out.txt";

open my $fh,'<',$infile or die "Couldnt open the file $infile:$!" ; 
open my $out,'>',$outfile or die "Cannot write to the file $!"; 
my $count = 0;
my $var = 0;
my @final=();

my @remove_power_list = ("vcchg","vccl","vss");

   while(<$fh>)
        {
            #chomp;
            foreach my $rem(@remove_power_list) {
                $var++;
        my $line = 'Power\s+information\s+for\s+' . "$rem";
          if($_ =~ /$line/g)
           {
             $count = $. + 11;
            }
          else      
          {
             if($count != 0 && $. < $count)
              {
                 }
             elsif($count != 0 && $. == $count)
                {
                  $count =0;
                  }         
             else
              {
                if($var ==1)
                 {
                 push(@final,$_);
                  }
                }     
            }
        }  
      $var=0;  
    }

foreach my $rem(@remove_power_list)
 { 
 foreach my $res (@final)
   {
        my $line = 'Power\s+information\s+for\s+' . "$rem";
          if($res =~ /$line/g)
           {
           $res =~ s/$res//isg;
            }          
        }       
     } 

foreach my $finalval (@final)
 {
     print $out $finalval;
    }          
 close($fh);       
close($out);

输出: (out.txt)

# Bind
     ::d::autoBindmap $intfcName 


    ############ Power information for vss #####################

    ############ Power information for vdd #####################
    #----------------------------
     #pg_vdd s100
    #----------------------------
     #Add pg_vdd_dl interface
    set  intfcName pg_vdd 1.0 s 100

     #Add Verilog port binding for vss
     ::d::autoBindmap $module pg_vdd $intfcName
    {
     VDD vss_dl;
     }


     #write component 
     ::d::writeLib $module

【讨论】:

  • 感谢您的回答。但是,我忘了提到 remove_power_list 数组会根据我在巨大脚本中的其他部分代码不断变化。那么,我们可以在 while 语句之前使用 for 循环来匹配这些行吗?另外,我需要删除“$p 的电源信息”行($p 是 vss),同时删除这 11 行。我也不提了。如果我不将打印语句放在“if”语句大括号中,我想我可以删除它。
  • 抱歉耽搁了。我正忙于其他事情。修改了代码。看看吧。
猜你喜欢
  • 2017-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-14
  • 1970-01-01
  • 2012-07-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多