PraveenKS
PraveenKS

Reputation: 1175

Split array element delimited with '.'

I am trying to read below CSV file content line by line in Perl.

CSV File Content:

A7777777.A777777777.XXX3604,XXX,3604,YES,9
B9694396.B216905785.YYY0018,YYY,0018,YES,13
C9694396.C216905785.ZZZ0028,ZZZ,0028,YES,16

I am able to split line content using below code and able to verify the content too:

@column_fields1 = split(',', $_);   
print $column_fields1[0],"\n";

I am also trying to find the second part on the first column of CSV file (i.e., A777777777 or B216905785 or C216905785) – the first column delimited with . using the below code and I am unable to get it.

Instead, just a new line printed.

my ($v1, $v2, $v3) = split(".", $column_fields1[0]);
print $v2,"\n";

Can someone suggest me how to split the array element and get the above value?

On my functionality, I need the first column value altogether at someplace and just only the second part at someplace.

Below is my code:

use strict;
use warnings;

my $dailybillable_tab_section1_file = "./sql/demanding_01_T.csv";
open(FILE, $dailybillable_tab_section1_file) or die "Could not read from $dailybillable_tab_section1_file, program halting.";

my @column_fields1;
my @column_fields2;

while (<FILE>) 
{
    chomp;
    @column_fields1 = split(',', $_);

    print $column_fields1[0],"\n";

    my ($v1, $v2, $v3) = split(".",$column_fields1[0]);
    print $v2,"\n";

    if($v2 ne 'A777777777')
        {
        …
        …
        …
    }
    else
    {
        …
        …
        …

    }

}
close FILE;

Upvotes: 0

Views: 119

Answers (2)

melpomene
melpomene

Reputation: 85757

split takes a regex as its first argument. You can pass it a string (as in your code), but the contents of the string will simply be interpreted as a regex at runtime.

That's not a problem for , (which has no special meaning in a regex), but it breaks with . (which matches any (non-newline) character in a regex).

Your attempt to fix the problem with split "\." fails because "\." is identical to ".": The backslash has its normal string escape meaning, but since . isn't special in strings, escaping it has no effect. You can see this by just printing the resulting string:

print "\.\n";  # outputs '.', same as print ".\n";

That . is then interpreted as a regex, causing the problems you have observed.

The normal fix is to just pass a regex to split:

split /\./, $string

Now the backslash is interpreted as part of the regex, forcing . to match itself literally.

If you really wanted to pass a string to split (I'm not sure why you'd want to do that), you could also do it like this:

split "\\.", $string

The first backslash escapes the second backslash, giving a two character string (\.), which when interpreted as a regex means the same thing as /\./.

Upvotes: 2

Dave Cross
Dave Cross

Reputation: 69224

If you look at the documentation for split(), you'll see it gives the following ways to call the function:

split /PATTERN/,EXPR,LIMIT

split /PATTERN/,EXPR

split /PATTERN/

split

In three of those examples, the first argument to the function is /PATTERN/. That is, split() expects to be given a regular expression which defines how the input string is split apart.

It's very important to realise that this argument is a regex, not a string. Unfortunately, Perl's parser doesn't insist on that. It allows you to use a first argument which looks like a string (as you have done). But no matter how it looks, it's not a string. It's a regex.

So you have confused yourself by using code like this:

split(".",$COLUMN_FIELDS1[0])

If you had made the first argument look like a regex, then you would be more likely to realise that the first argument is a regex and that, therefore, a dot needs to be escaped to prevent it being interpreted as a metacharacter.

split(/\./, $COLUMN_FIELDS1[0])

Update: It's generally accepted among Perl programmers, that variable with upper case names are constants and don't change their values. By using upper case names for standard variables, you are likely to confuse the next person who edits your code (who could well be you in six months time).

Upvotes: 1

Related Questions