Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi, being a newbie to perl how do I access the individual elements of $_. For example mylist.dat looks like this
a,b,c,d,e,f,g 1,2,3,4,5,6,7 x,y,z,s,t,u,v
This is not a CSV file by the way
$id = 1 open(MYFILE,"/var/tmp/mylist.dat") or die "Cant open mylist.dat" while (<DMPLD>) { chomp; die "Request Id $id already present in file\n" if $_ eq $id; } close DMPLD;
This doesn't find the second row in the file. So how do I reference the first element of $_ (with a field seperator of comma) ? I tried using $_[0] but that doesn't work. Thanks

Replies are listed 'Best First'.
Re: Access elements of $_
by moritz (Cardinal) on Aug 12, 2010 at 12:24 UTC
    You have to split the string into a list or array before you can access individual array items.

    I can recommend reading perlintro.

    Perl 6 - links to (nearly) everything that is Perl 6.
      Thanks
Re: Access elements of $_
by AnomalousMonk (Archbishop) on Aug 12, 2010 at 12:40 UTC
    This doesn't find the second row in the file.

    Which file: the one accessed by the file handle  MYFILE or by the  DMPLD handle?

    Maybe try writing a program which opens a file, reads and prints each line in a  while loop, and then closes the file. This might be a good foundation for your ultimate goal.

    As moritz suggested, you might then want to try splitting each line as you go through the  while loop to access its fields.

    [H]ow do I reference the first element of $_ ...

    $_ is a scalar; it has no elements. It may be a scalar that is a reference to an array, in which case  $_->[0], $_->[1], ... would access the first, second, etc., elements of the array.

      Actually, I just did this to fix it following an earlier suggestion
      $id = 1 open(MYFILE,"/var/tmp/mylist.dat") or die "Cant open mylist.dat" while (<MYFILE>) { chomp; split/,/; die "Request Id $id already present in file\n" if $_[0] eq $id; } close MYFILE;
Re: Access elements of $_
by shmem (Chancellor) on Aug 12, 2010 at 14:03 UTC
    $id = 1; # <--- semicolon was missing open(MYFILE,"/var/tmp/mylist.dat") or die "Cant open mylist.dat" while (<MYFILE>) { # <--- wrong file handle fixed chomp; die "Request Id $id already present in file\n" if $_ eq $id; } close MYFILE;

    $_, which gets assigned to by <MYFILE> in a while loop, is a scalar.
    As such, it can hold a string or a number. The line is not magically split at the comma*. So, $_ just holds the entire line.

    The operator eq compares its operands stringwise and returns true if both are equal. Perhaps you want to match?

    die "Request Id $id already present in file\n" if /$id/;

    The match operator m// is by default bound to $_; to match against something else you need the binding operator =~:

    while (my $line = <MYFILE>) { chomp $line; die "Request Id $id already present in file\n" if $line =~ /$id/ +; }

    If you really want an array and compare $id against its first element, you have to split the line into an array:

    my @array = split /,/, $_; die "Request Id $id already present in file\n" if $array[0] eq $id +;

    Note that split by default splits into the array @_ whose first element is $_[0] - but this usage is deprecated.

    *) for magical split, look up the -a, -n, -p and -F switches, and the array @F in perlrun.

      I'm a bit puzzled now. I tried your solution and it works fine but so does this
      $id = 1; # <--- semicolon was missing open(MYFILE,"/var/tmp/mylist.dat") or die "Cant open mylist.dat" while (<MYFILE>) { # <--- wrong file handle fixed chomp; split /,/; die "Request Id $id already present in file\n" if $_[0] eq $id; } close MYFILE;
      What is the difference in using an array or doing it as above ? I thought split will split a string into an array of strings anyway. Hence I'm a bit puzzled as to why I explicitly have to use an array as per your example. Is this better programming practice ?
        Hence I'm a bit puzzled as to why I explicitly have to use an array as per your example. Is this better programming practice ?

        Yes, it is - and precisely because you are puzzled :-)

        As I said above, split by default splits into the array @_ whose first element is $_[0] - and it's a deprecated usage because it leads people to be puzzled, and because @_ also is the argument array inside subroutines; so using implicit split inside subs is probably a bad idea.

        Oops just realised you answered that by saying it's deprecated. Apologies I should have seen this earlier