Best way to read a file into a multi-dimensional array, and skip lines that contain certain information in Perl

Viewed 93

I am new to Perl coding, and have come across a issue that I cannot find a away around.

I am attempting to read a file and place the information into a multi-dimensional array, this is working fine, however I have a need where certain lines in the file need to be skipped from being added to the array.

The code I am using looks like this:

sub read_files {
    @fields = ();
    open($input_data, '<', $file) or die "Could not open '$file' $!\n";  # Open the CSV file and read its contents, if the file cannot be opened display an error and exit the program
    while (<$input_data>)  # While there is data to be read
    {
        chomp;
        push @fields, [split /\s+/];
    }
}

the lines in the file that I want to skip look like this:

121    0 -blank-                 BlockSize=2048 BlockCount=536516096 MediumType=10 Location=121/1/1 BlockAddressable=0 fsCapability=iso                     -          -          HD-WO vol1
 344    0 --bad--                 BlockSize=0 BlockCount=0 MediumType=0 Location=344/1/1 BlockAddressable=0                                                  -          -          -     icas

770    0 -XXXXX-                 -                                                                                                                          -          -          HD-WO icas

Vaild lines would look similar to this:

 753 1060 EY_icas_0416G           BlockSize=2048 BlockCount=1550534 MediumType=10 Location=753/1/1 BlockAddressable=0 PhysBlockCount=1550534 state=regular   1572740385 1793466337 HD-WO icas
 754 1061 NG_icas_0186I           BlockSize=2048 BlockCount=445776 MediumType=10 Location=754/1/1 BlockAddressable=0 PhysBlockCount=445776 state=regular     1572741506 1793391106 HD-WO icas
 755 1062 GJ_icas_0060E           BlockSize=2048 BlockCount=230419 MediumType=10 Location=755/1/1 BlockAddressable=0 PhysBlockCount=230419 state=regular     1572746004 1793444405 HD-WO icas

Any help would be much appreciated

Additionally when using [split /\s+/]; to split the line read when there is a space, how can I add a comma "," to the list also ?

2 Answers

The OP's question is not complete.

OP should specify more complete data sample with indication what lines should be skipped.

Following code sample is based on provided data but perhaps far from desired solution due absence of important information in the question.

For demonstration purpose in the code defined regex $skip_pattern to skip a lines starting with # symbol.

Empty lines also skipped as sanity check.

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

my @data;
my $skip_pattern = qr/^#/;

while( <DATA> ) {
    next if /^\s+\z/;
    next if /$skip_pattern/;
    push @data, [split /[\s,]+/];
}

say Dumper(\@data);

exit;

__DATA__
# Sample data
121    0 -blank-                 BlockSize=2048 BlockCount=536516096 MediumType=10 Location=121/1/1 BlockAddressable=0 fsCapability=iso                     -          -          HD-WO vol1
# Line to skip
122    1 -blank-                 BlockSize=4096 BlockCount=536516096 MediumType=10 Location=121/1/1 BlockAddressable=0 fsCapability=iso                     -          -          HD-WO vol1

Output

$VAR1 = [
          [
            '121',
            '0',
            '-blank-',
            'BlockSize=2048',
            'BlockCount=536516096',
            'MediumType=10',
            'Location=121/1/1',
            'BlockAddressable=0',
            'fsCapability=iso',
            '-',
            '-',
            'HD-WO',
            'vol1'
          ],
          [
            '122',
            '1',
            '-blank-',
            'BlockSize=4096',
            'BlockCount=536516096',
            'MediumType=10',
            'Location=121/1/1',
            'BlockAddressable=0',
            'fsCapability=iso',
            '-',
            '-',
            'HD-WO',
            'vol1'
          ]
        ];
open(F, "$file") or die "Could not open '$file' : $!\n";
local $/ = undef;
$_ = <F>;
close(F);

s/^(?!\d+\s+\d+\s+[\w-]+\s+(?:[\w-]+=[\w\/-]+\s+)+\d+\s+[\w-]+\s+[\w-]+\s*).*[\n\r]+//gm;

# now you have in $_ just proper formatted lines
# split them to the array as desired
Related