如何在Perl中的某些关键字之后替换行

时间:2018-06-26 13:47:14

标签: shell perl

rerun.txt

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

({abcd$var12 ... {{ 1}}(在我的代码中)

我要在$num中搜索$var,并用cell.txt(如area)替换$num(对应的下一行)< / p>

cell.txt

area : 1

Perl代码

  cell (a)  {
     area :  2
  }

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

  cell (d)  {
     area :  2.7
   }

2 个答案:

答案 0 :(得分:0)

我依靠一些更高级的正则表达式来尝试防御可能的输入并结合一些步骤。 docs on 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 ...

答案 1 :(得分:-1)

此解决方案使用第一列作为键,第二列作为值,将 rerun 数据读取到哈希%rerun中。根据可能的键集构建正则表达式模式$re并进行编译

cell.txt的全部内容都被读入$cell,以使其更容易处理多行字符串。找到每次出现cell (x) {及其后继area : 99.99x%rerun的键之一的情况,随后的99.99被替换为哈希元素的值

找到并替换所有内容后,新的$cell将打印到STDOUT

use strict;
use warnings 'all';
use autodie;

my %rerun = do {
    open my $fh, '<', 'rerun.txt';
    map { /[^,\s]/g } <$fh>;
};

my $cell = do {
    open my $fh, '<', 'cell.txt';
    local $/;
    <$fh>;
};

my $re = join '|', sort { length $b <=> length $a } keys %rerun;
$re = qr/$re/;

$cell =~ s/ \b cell \s* \( \s* ( $re ) \s* \) \s* \{ \s* area \s* : \s* \K [\d.]+ /$rerun{$1}/gx;

print $cell;

输出

  cell (a)  {
     area :  1
  }

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

  cell (d)  {
     area :  4
   }