user1495523
user1495523

Reputation: 505

perl split file based on file string

I am trying to split a very large file into smaller files based string within the file.

eg. Input file

 Block(A){
   Block_area : 2.6112;
   Block_footprint : 3BAA5927A22E66B0AE1214A806440F12;
 }
 Block(B){
   Block_area : 2.6112;
   Block_footprint : 3BAA5927A22E66B0AE1214A806440F12;
 }
 Block(C){
   Block_area : 2.6112;
   Block_footprint : 3BAA5927A22E66B0AE1214A806440F12;
 }

I want to create three files each containing the data within the brakets

Could you please let me know where I am getting it wrong. my perl code

while (<PR>) {
    if ($_ =~ ' Block\('))
    {
        chomp;
    close (PW);
        $textcell = $_;
        $textcell =~ s/Block\(//g;
        $textcell =~ s/\)\{//g;
    open (PW, ">$textcell.txt") or die "check file";
    }
    if ( /^  Block\($textcell\)/../^  }/)
    { print PW  $_;}
}

The desired files are being created but are empty.

regards


Desired output, three files:

A.txt

 Block(A){
   Block_area : 2.6112;
   Block_footprint : 3BAA5927A22E66B0AE1214A806440F12;
 }

B.txt

 Block(B){
   Block_area : 2.6112;
   Block_footprint : 3BAA5927A22E66B0AE1214A806440F12;
 }

C.txt

 Block(C){
   Block_area : 2.6112;
   Block_footprint : 3BAA5927A22E66B0AE1214A806440F12;
 }

Upvotes: 0

Views: 186

Answers (2)

mpapec
mpapec

Reputation: 50637

I would suggest changing approach and read file in blocks instead of lines,

use strict;
use warnings;
use 5.010;
use autodie;

# input record separator is now '}' followed by old value of separator (i.e \n)
local $/ = "}$/";

while (<>) {
  my ($file) = m|\( (.+?) \)|x or next;

  open my $fh, ">", "$file.txt";
  print $fh $_;
  close $fh;
}

Upvotes: 1

Borodin
Borodin

Reputation: 126722

The problem is that your tests exclude anything that isn't a Block() line. You do nothing at all for any other forms of the line. In addition, your second if statement is checking that there are two spaces before Block, which never occurs.

This is how I would write it. It assumes at least version 10 of Perl 5 so that I can use autodie instead of checking the success of each open call explicitly. Note that I have used the /x modifier on my regular expression, so spaces and tabs are insignificant and I can use them to make the regex more readable.

use strict;
use warnings;
use 5.010;
use autodie;

open my $in_fh, '<', 'blocks.txt';

my $out_fh;

while (<$in_fh>) {
  open $out_fh, '>', "$1.txt" if / Block \( (\w+) \) /x;
  print $out_fh $_ if $out_fh;
}

Upvotes: 1

Related Questions