2

@mytitlesたとえば、などの多くのタイトルを含むtitle1という配列がありますtitle2Superdataset各タイトルに関する情報を含む「 」というファイルがあります。ただし、に関連する情報title1は 6 行の場合があり、の情報はtitle230 行 (ランダム) の場合があります。titlex( a の)各情報は " " で始まり " Reading titlex" で終わりDone reading titlexます。

各タイトルのこれらの情報行から、いくつかのデータを抽出する必要があります。Done reading titlexこの必要なデータが毎回" " の直前の 2 行にあるのはラッキーだと思います

したがって、私の " Superdataset" は次のようになります。

読書タイトル1  
 ランダム情報 line1
 ランダム情報 line2
 ランダム情報 line3
 ランダム情報 line4
 ランダム情報 line5
 私の収入は6000です
 私の費用は1000です
タイトル 1 を読み終えました
読書タイトル2
 ランダム情報 line6
 ランダム情報 line7
 ランダム情報 line8
 ランダム情報 line9
 ランダム情報 line10
 ランダム情報 line11
 ランダム情報 line12
 ランダム情報 line13
 ランダム情報 line14
 私の収入は11000です
 私の費用は9000です
タイトル 2 を読み終えました

経費の総額と収入の総額が必要です。助言がありますか?PS-配列には複雑な名前が付けられており、次のような単純なものではありませんtitlex

4

3 に答える 3

0

これは、データを使用可能な形式に丸呑みする最初のパスです。

use warnings;
use strict;
use autodie;

my $input_filename = 'example';
open my $input, '<', $input_filename;
my %data;
{
  my $current_title;

  while(<$input>){
    chomp;
    if( /^Reading (.*?)\s*$/ ){ # start of section
      $current_title = $1;
    }elsif( not defined $current_title ){ # outside of any section
      # invalid data
    }elsif( /^Done reading (.*)/ ){ # end of section
      die if $1 ne $current_title;
      $current_title = undef;
    }else{ # add an element of section to array
      push @{ $data{$current_title} }, $_;
    }
  }
}
close $input;

作成されたデータ構造を使用して、総収入と支出を決定します。

my( $earnings, $expenses );
for my $list( values %data ){
  for( @$list ){
    if( /earnings are (\d+)/ ){
      $earnings += $1;
    }elsif( /expenses are (\d+)/ ){
      $expenses += $1;
    }
  }
}

print "earnings $earnings\n";
print "expenses $expenses\n";

代わりに、コンピューターにとってより便利な形式で印刷します。

use YAML 'Dump';
print Dump \%data;
---
タイトル1:
  - 「ランダム情報 line1」
  - 「ランダム情報 line2」
  - 「ランダム情報 line3」
  - 「ランダム情報 line4」
  - 「ランダム情報 line5」
  - 「私の収入は 6000 です」
  - 「私の出費は 1000 です」
タイトル2:
  - 'ランダム情報 line6'
  - 'ランダム情報 line7'
  - 'ランダム情報 line8'
  - 'ランダム情報 line9'
  - 'ランダム情報 line10'
  - 'ランダム情報 line11'
  - 'ランダム情報 line12'
  - 'ランダム情報 line13'
  - 'ランダム情報 line14'
  - 「私の収入は 11000 です」
  - 「私の経費は 9000 です」
于 2011-12-17T02:32:46.710 に答える
0

関連する行の前の行が何であるかを予測できない限り、フリップフロップ演算子は最適化によってあまり役に立ちません。バッファ配列を使用して、収益と費用の後の行と一致させる方が簡単だと思います。

#!/usr/bin/perl
use strict;
use warnings;

my @buffer;
my ($earnings, $expenses);

for my $line (<DATA>) {
    shift @buffer if @buffer > 2;
    push @buffer, $line;

    next if $line !~ /^Done reading/;

    $earnings += $1 if $buffer[0] =~ /(\d+)$/;
    $expenses += $1 if $buffer[1] =~ /(\d+)$/;
}
print "Total earnings: $earnings\n";
print "Total expenses: $expenses\n";

__DATA__
Reading title1  
 random info line1
 random info line2
 random info line3
 random info line4
 random info line5
 my earnings are 6000
 my expenses are 1000
Done reading title1
Reading title2
 random info line6
 random info line7
 random info line8
 random info line9
 random info line10
 random info line11
 random info line12
 random info line13
 random info line14
 my earnings are 11000
 my expenses are 9000
Done reading title2

出力:

Total earnings: 17000
Total expenses: 10000
于 2011-12-18T22:11:56.740 に答える
0

「範囲」演算子を使用すると、次のことができます。

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my $begin_stanza = qr/^Reading/i;
my $endof_stanza = qr/^Done reading/i;
my ( $title, @lines );
my ( $value, $total_earnings, $total_expenses );
while (<DATA>) {
    chomp;
    if ( m{$begin_stanza} .. m{$endof_stanza} ) {
        if ( m{$begin_stanza\s+(.+)} ) {
            $title = $1;
            @lines = ();
            next;
        }
        if ( m{$endof_stanza} ) {
            ($value) = ( $lines[0] =~ m{(\d+)} );
            $total_earnings += $value;
            ($value) = ( $lines[1] =~ m{(\d+)} );
            $total_expenses += $value;
            print join "\n", $title, @lines, "\n";
            next;
        }
        shift @lines if @lines == 2;
        push  @lines, $_;
    }
}
printf "Total Earnings = %7d\n", $total_earnings;
printf "Total Expenses = %7d\n", $total_expenses;
__DATA__
Reading title1
 random info line1
 random info line2
 random info line3
 random info line4
 random info line5
 my earnings are 6000
 my expenses are 1000
Done reading title1
Reading title2
 random info line6
 random info line7
 random info line8
 random info line9
 random info line10
 random info line11
 random info line12
 random info line13
 random info line14
 my earnings are 11000
 my expenses are 9000
Done reading title2

...結果は次のとおりです。

title1
 my earnings are 6000
 my expenses are 1000

title2
 my earnings are 11000
 my expenses are 9000

Total Earnings =   17000
Total Expenses =   10000
于 2011-12-17T15:36:56.350 に答える