annel
annel

Reputation: 59

How to extract certain part of the text into another file?

Here is my code. I wish to extract part of the text and write into another file. The loop of the code do not stop at my selected range of text. It read until the final match line of word. Please advise me. Thanks. For example, I need to extract the $ NAME: sandy until $$.TO and then join with the contents inside $NAME: patrick which is start from G1 until $$SRU.

TEXT:

$ NAME : corry  
$$.Inc s d
$$.Oc s
$$.TO

G1 ty n1 EE EE M T1 T2 $$SRU
G2 n1 y OO OO M T3 T4 $$SRU    
$$.EON

$ NAME : patrick    
$$.Inc c d
$$.Oc c
$$.TO

G1 td n3 EE EE M T5 T6 $$SRU      
G2 n3 y OO OO M T7 T8 $$SRU    
$$.EON
$ NAME : sandy    
$$.Inc k l
$$.Oc l
$$.TO

G1 td n3 FF FF M R5 R6 $$SRU      
G2 n3 y OO OO N R7 R8 $$SRU    
$$.EON

OUTPUT:eg.

$ NAME : sandy    #from sandy section
$$.Inc k l      #sandy
$$.Oc l         #sandy
$$.TO           #sandy
G1.G1o.n ty n1 EE EE M T1 T2 $$SRU #from Patrick section
G2.G2o.n n1 y OO OO M T3 T4 $$SRU   #Patrick 
Fe.id.n ty n1 EE EE N T1 T2 $$SRU #corry
Fr.in.p n1 y OO OO N T3 T4 $$SRU   #corry 
$$.EON     #Patrick

CODE:

use strict;
use warnings;

open my $F1, '<', 'testing.txt' or die "failed $!";
open my $F2, '>', 'out.txt' or die "failed $!";

while (<$F1>) {
 if (/^\$ NAME : sandy/../\$.TO/) {
 print $F2 $_;
 }
 if (/^\$ NAME : patrick/../\$.EON/) {
 if(/^G1/../\$SRU/){
 s/G1/G1.G1o.n/g;
 print $F2 $_;}
}

 }
close $F1;
close $F2;

Upvotes: 2

Views: 174

Answers (2)

Suic
Suic

Reputation: 2501

You can parse all the file to one big hash, and do everything you want with its elements: combine, change etc

use strict;
use warnings;
use Data::Dumper;

open my $F1, '<', 'in' or die "failed $!";
open my $F2, '>', 'out.txt' or die "failed $!";


my %elements;
my $current_element;
while (<$F1>) {
    if ( /^\$ NAME : (\w+)/ .. /\$\$[.]EON/ ) {
        if ( /^\$ NAME : (\w+)/ ) {
            $current_element = $1;
        }
        if ( /^G1/ ) {
            $elements{$current_element}->{g1} .= $_;
        }
        elsif ( /^G2/ ) {
            $elements{$current_element}->{g2} .= $_;
        }
        elsif ( ! /\$\$[.]EON/ ) {
            $elements{$current_element}->{text} .= $_;
        }

    }
}
close $F1;
$elements{patrick}->{g1} =~ s/G1/G1.G1o.n/;
$elements{patrick}->{g2} =~ s/G1/G2.G2o.n/;
$elements{corry}->{g1} =~ s/G1/Fe.id.n/;
$elements{corry}->{g2} =~ s/G2/Fr.in.p/;
print $F2 "$elements{sandy}->{text}$elements{patrick}->{g1}$elements{patrick}->{g2}$elements{corry}->{g1}$elements{corry}->{g2}\n\$\$.EON";
close $F2;

this will parse all the file to hash that looks like:

  1. $elements{'name (for example patric'}->{text} = 'everithing in patric section except G1 and G2 section'
  2. $elements{'name (for example patric'}->{g1} = 'G1 section'
  3. $elements{'name (for example patric'}->{g2} = 'G2 section'

so if you want to combine text from sandy and G1 from patric you can do

my $sandy_patric = $elements{sandy}->{text}.$elements{patrick}->{g1};

Upvotes: 2

Birei
Birei

Reputation: 36262

You were not far from a solution. I would set a flag when inside the patrick section I find the line that begins with G1, and I would save each line in an array (after substitution) to append it after processing the sandy section:

#!/usr/bin/env perl

use warnings;
use strict;

my (@patrick, $flag);

open my $F1, '<', 'testing.txt' or die "failed $!";
open my $F2, '>', 'out.txt' or die "failed $!";

while ( <$F1> ) { 
    if (/^\$ NAME : sandy/../\$\.TO/) {
        print $F2 $_; 
    }   
    if (/^\$ NAME : patrick/../\$\.EON/) {
        if ( m/\AG1/ ) { $flag = 1 } 
        if ( $flag ) { 
            s/\A(G\d+)/$1.$1o.n/;
            #print $F2 $_;
            push @patrick, $_; 
        }      
    }   

}

print $F2 $_ for @patrick;

close $F1;
close $F2;

It will create a file out.txt with content:

$ NAME : sandy    
$$.Inc k l
$$.Oc l
$$.TO
G1.G1o.n td n3 EE EE M T5 T6 $$SRU      
G2.G2o.n n3 y OO OO M T7 T8 $$SRU    
$$.EON

Upvotes: 0

Related Questions