需要使用perl将文件中的模式移动到同一文件中的不同位置吗?

时间:2016-09-20 08:02:42

标签: perl file

我的输入文件格式为

hidestart 
machine learning
hideend

rule abc {
  hidestart
   Keep Learning
  hideend
   -abc [ time=good] 
}

rule abc1 {
   Keep Learning

   -abc1 [ time1=fail] 
}


Rule “abc” { 
   hidestart 
    dp a.E_t_C1 temp –be_good NL LP -expr " (cnt(a.E_t_C1) > 0) ? expr(- (minus (pt(a.E_t_C1,ab)) / at(temp)*fr/pr_1)) : 1 " < 0 > 1 
   hideend 
   ….. 
   -CDE [ ABC_TYPE = “temp_EOL”] 
   -CDE [ TMP_RUL = “a.E” ] 
   .. .. .. 
   -comment "keepTrying" 
}

我希望将位于规则块内的hideend移动到最后并且在花括号之前。仅当规则块具有hidestart命令时,才应插入/移动此hideend。此外,位于此规则块之外的hidestart / hidened应保持不变。

预期产出:

hidestart 
machine learning
hideend

rule abc {
  hidestart
   Keep Learning
   -abc [ time=good] 
  hideend
}
rule abc1 {
   Keep Learning

   -abc1 [ time1=fail] 
}

Rule “abc” { 
   hidestart 
    dp a.E_t_C1 temp –be_good NL LP -expr " (cnt(a.E_t_C1) > 0) ? expr(- (minus (pt(a.E_t_C1,ab)) / at(temp)*fr/pr_1)) : 1 " < 0 > 1 

   ….. 
   -CDE [ ABC_TYPE = “temp_EOL”] 
   -CDE [ TMP_RUL = “a.E” ] 
   .. .. .. 
   -comment "keepTrying" 
  hideend
}

我当前的代码,实际上是删除了位于块之外的hideend,并且还将hideend添加到我没有hidestart的规则块中。请帮我修复下面的代码

!/usr/bin/env perl
use strict();
use warnings();
use Data::Dumper;
my $ruleData=0;
my $goldenData = $ARGV[0];
open( $fopen, "< $goldenData") or die "cannot open $!";
while(<$fopen>) {
 if ( $_ =~ /^\s*rule(.+)/gi ) {
   print "rule$1\n";
   while($tmp=<$fopen> ) {
     if ( $tmp =~ /^\s*hideend/gi ) { next; }
     if ( $tmp =~ /^\s*\}/gi ) {
        print "hideend\n$1\}\n";
     } else {
         print "$tmp";
     }
   }
  close($tmp);
 } else {
    print "$_";
 }
}
close($fopen);

如果有任何问题,请告诉我。

提前致谢。

此致 Divesh

2 个答案:

答案 0 :(得分:0)

请试试这个:

#!/usr/bin/env perl
use strict();
use warnings();
use Data::Dumper;
my $ruleData=0;
my $goldenData = $ARGV[0];
open(IN, "<$goldenData") or die "cannot open $!";
local $/; $_=<IN>; my $tmp=$_;
close(IN);

my $CurBrLoopMany = qw/((?:[^{}]*(?:{(?:[^{}]*(?:{(?:[^{}]*(?:{[^{}]*})*[^{}]*)*})*[^{}]*)*})*[^{}]*)*)/;

my ($_pre,$_match,$_post) = "";
while($tmp=~m/rule([\"A-z\s]*)\{$CurBrLoopMany\}/gis)
{
    $_pre = $_pre.$`; $_match = $&; $_post = $';
    $_match=~s/\s*hideend//g;
    $_match=~s/\}/ hideend \n}/i;
    $_pre = $_pre.$_match; $tmp = $_post;
}
if(length $_pre) {  $tmp = $_pre.$_post;  }

print $tmp;

感谢。

答案 1 :(得分:0)

这适用于您的示例文件。并且,希望这些评论能够清楚说明发生了什么,以便您可以解决任何问题。

#!/usr/bin/perl

use strict;
use warnings;

my ($found_hidestart, $found_hideend);

while (<>) {
  # Only process within a rule block
  if (/^rule\s+\S+\s+{/i .. /^}/) {
    # If we find 'hidestart' remember that
    if (/\bhidestart\b/) {
      $found_hidestart = 1;
    }

    # If we find 'hideend' (and have already found 'hidestart')
    # remember that and don't print this line.
    if (/\bhideend\b/ && $found_hidestart) {
      $found_hideend = 1;
      next; # skip printing
    }

    # If we're at the end of a block and we've previously found
    # both 'hidestart' and 'hideend', then print 'hideend'.
    if (/^}/) {
      print "  hideend\n" if $found_hidestart and $found_hideend;
      # Forget what we've previously found
      $found_hidestart = $found_hideend = 0;
    }
  }
  print;
}

它被编写为Unix过滤器 - 因此它从STDIN读取并写入STDOUT。这比打开显式文件名更灵活。假设这是在一个名为reformat的文件中,你可以这样称呼它:

$ ./reformat < your_existing_file > your_new_file

更新:我已稍微更新了正则表达式,因此它会处理您展开的示例。