首页 > 解决方案 > 如何在perl中的某个关键字之后替换一行

问题描述

重新运行.txt

a,1
b,2
c,3
d,4

( a, b, c, dare $varand 1, 2...$num在我的代码中)

我想在这个文件中搜索并用(like)$var替换(其cell.txt对应area的下一行)$numarea : 1

细胞.txt

  cell (a)  {
     area :  2
  }

  cell (b)  {
     area :  2.3
   }
  cell (c)  {
     area :  2.5
   }

  cell (d)  {
     area :  2.7
   }

Perl 代码

#!usr/bin/perl

use warnings;
use strict;

open( my $fh1, "rerun.txt" ) or die "Couldn't open file file.txt, $!";

my $word  = 0;
my $input = "area";
my $num;
my $var;
my $line;
my $a     = 0;
my $flag  = 0;
my $flag1 = 0;

while ( <$fh1> ) {

    ( $var, $num ) = split ",";    # splitting acc to comma

    open( my $fh, "cell.txt" ) or die "Couldn't open file file.txt, $!";

    while ( my $line1 = <$fh> ) {    # while in the file opened

        $line1 =~ s/^\s+//;         # removing spaces
        my @word = split " ", $line1;    # splitting acc to spcaes

        foreach $word ( @word ) {

            $word =~ s/[(,),]//g;        # excluding all brackets (,),{,}

            if ( $word eq $var ) {
                $flag = 1;
            }

            if ( $flag == 1 ) {

                if ( $word eq "area" ) {

                    $a = $.;             # saving the line number
                    system( "sed -i '$a s/.*/\t area : $num /' cell.txt" );
                    goto L1;
                }
            }
        }
    }

    L1:

    close( $fh );
}

close( $fh1 );

标签: shellperl

解决方案


我依靠一些更高级的正则表达式来尝试对可能的输入进行防御并结合一些步骤。上的文档goto建议last(在您的情况下last LABEL)作为替代方案,但我希望 OP 不会因为我重复某些人共享的教条而感到受伤。我的版本打印到标准输出而不是更改原始文件,但应该足够接近。打印一些预期的输出会有所帮助,但希望我猜对了。

Borodin比我早几分钟完成,我没有看到他的帖子,这在某些方面是一种更高级的方法。根据相同的建议,我删除了对Regexp::Common模块的引用,虽然相关,但我同意这超出了需要。

#!/usr/bin/env perl

use Modern::Perl;

open(my $fh, '<', 'rerun.txt') or die "Could not open rerun.txt: $!";
my %new_area;
foreach (<$fh>) {
    chomp;
    my ($k, $v) = split ',';
    die "invalid rerun format" unless ($k =~ /^\w+$/ and $v =~ /^[\d.]+$/);
    $new_area{ $k } = $v;
}

open($fh, '<', 'cell.txt') or die "Could not open cell.txt: $!";
my $area_key;
while (<$fh>) {
    if ( /^\s* cell \s*\(\s*(\w+)\s*\)\s* { \s*$/x ) {
        $area_key = $1;
    }
    elsif (/^\s* } \s*$/x) {
        undef $area_key
    }
    elsif ( defined($area_key) and /\barea\b/ and
            exists $new_area{ $area_key }
    ) {
        s/(area\s*:\s*)[\d.]+/$1$new_area{$area_key}/
    }

    print;
}

输出:

  cell (a)  {
     area :  1
  }

  cell (b)  {
     area :  2
   }
  cell (c)  {
     area :  3
   }

... etc ...

推荐阅读