как заменить строку после определенного ключевого слова в perl - PullRequest
0 голосов
/ 26 июня 2018

rerun.txt

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

(a, b, c, d - $var и 1, 2 ... $num в моем коде)

Я хочу найти $var в cell.txt и заменить area (соответствующую ему следующую строку) на $num (например, area : 1) в этом файле

cell.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 );

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Я полагаюсь на несколько причудливых регулярных выражений, чтобы попытаться защититься от возможного ввода и объединить некоторые шаги. В документах по goto предлагается last (в вашем случае last LABEL) в качестве альтернативы, но я надеюсь, что ОП не пострадает от моего повторения догмы, разделяемой немного. Моя версия печатается на стандартный вывод вместо изменения исходного файла, но должна быть достаточно близко. Было бы полезно напечатать некоторые ожидаемые результаты, но, надеюсь, я угадала.

Бородин закончил за несколько минут до меня, и я не увидел его публикации, что в некотором смысле является более продвинутым подходом. По предложению из того же я удалил ссылку на модуль 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 ...
0 голосов
/ 26 июня 2018

Это решение считывает данные rerun в хэш %rerun, используя первый столбец для ключей и второй для значений. Шаблон регулярного выражения $re строится из набора возможных ключей и компилируется

Полное cell.txt считывается в $cell, чтобы упростить обработку многострочных строк. Каждое вхождение cell (x) { со следующим area : 99.99 и где x является одним из ключей %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 }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...