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

I have a line from a file that looks like

directive thing1 thing2

where thing2 is optional and defaults to thing1. I'm currently doing

my ($first, $second) = [(split)[1,-1]]; $second = $first unless defined $second;
I had been hoping that the slice would always give me 2 values, even if they were from the same aray element, but no such luck. Does anyone have a better way of doing this?

Thanks,
Ira

"So... What do all these little arrows mean?"
~unknown

Replies are listed 'Best First'.
Re: split'ing lines with variable number of fields
by wog (Curate) on Jun 20, 2001 at 01:15 UTC
    You have the right idea but your syntax is off. The []s create a refrenence to an array (when they don't extract elements from one), so putting those around the split causes problems.

    If you care about the directive part, then I'd think it would be better to split once and use:

    my ($command, $first, $second) = (split)[0,1,-1];
      Yes, you are right about the extra brackets. But the rest is more complicated.
      my ($command, $first, $second) = (split) [0, 1, -1]; $second = $first unless defined $second;
      will only "work" because of a bug in Perl. It's still present in perl5.6.1, however, it's fixed in the development release. Index -1 should always be the last element. Regardless of how many elements there are in the list. The bug, however, is that when indexing over the result of a split, you cannot "reuse" elements. Repeating indexes result in undef. And when there are only two elements in the split, 1 and -1 will point to the same element - making $second undefined.

      With the development version of Perl, you could just do:

      my ($command, $first, $second) = (split) [0, 1, -1];
      and $second will be the right thing: the last element of the split. Hence, if there are just two items, $second will be the same as $first, just what you want.

      Luckely, the line

      $second = $first unless defined $second;
      won't harm you in the development version, as $second will be defined, so no assignment is done.

      -- Abigail

        Exactly what I wanted to know.

        Thanks!!!
        Ira

        "So... What do all these little arrows mean?"
        ~unknown

Re: split'ing lines with variable number of fields
by larryk (Friar) on Jun 20, 2001 at 01:38 UTC
    damn - I always get beaten to the first reply! the now* obligatory "well here's my 0.02p worth".

    Perl provides the ||= orequals operator which is used in the following way...

    $second ||= $first;
    Your code above allows for $second to be 0 (zero) and is perfectly readable. This (||=) way will not test for defined but for a true value so if $second is not allowed to be 0 (zero) then this is ideal (and more succinct). Otherwise, leave it how it is.

    Hope this helps, larryk

    * now that I'm not first to reply!

    "Argument is futile - you will be ignorralated!"