Earlier I've posted a problem asking Why does this code not work using split and array slices. Read that and try to solve it yourself before reading this. Here is my solution:

Let's try the first script:

examples/split_on_the_fly.pl



my $str = "root:*:0:0:System Administrator:/var/root:/bin/sh"; my $indexes="0,4"; ######## HERE#### my ($username, $real_name) = (split /:/, $str)[$indexes]; ##and HERE## print "$username

"; print "$real_name

";

$ perl split_on_the_fly.pl root

Always use strict and use warnings

As I've mentioned in other places, one should always use strict and always use warnings in Perl 5.

Adding them to this script will yield this code:

examples/split_on_the_fly_warnings.pl



use strict; use warnings; my $str = "root:*:0:0:System Administrator:/var/root:/bin/sh"; my $indexes="0,4"; ######## HERE#### my ($username, $real_name) = (split /:/, $str)[$indexes]; ##and HERE## print "$username

"; print "$real_name

";

And this output:

$ perl split_on_the_fly_warnings.pl Argument "0,4" isn't numeric in list slice at split_on_the_fly_warnings.pl line 7. root Use of uninitialized value $real_name in concatenation (.) or string at split_on_the_fly_warnings.pl line 9.

That in itself might not help with the exact solution, but at least it points in some direction. We can read about the Argument ... isn't numeric in numeric ... warning, the first in our output.

That and reading again the article about split and about array slicing might lead us to the realization that instead of a string in which we separate numbers by a comma, we need to use a list of numbers (which in the Perl syntax are separated by a comma) as the index in the array slice.

That's what we do in our solution. We replaced the $indexes scalar by the @indexes array, and instead of the string "0,4" we have the individual numbers (0, 4).

examples/split_on_the_fly_fixed.pl



use strict; use warnings; my $str = "root:*:0:0:System Administrator:/var/root:/bin/sh"; my @indexes = (0, 4); ######## HERE#### my ($username, $real_name) = (split /:/, $str)[@indexes]; ##and HERE## print "$username

"; print "$real_name

";

Running the script looks like this:

$ perl split_on_the_fly_fixed.pl root System Administrator

Stand-alone Array slice

The second experiment, that as I assume was an attempt to simplify the code and find a solution that way, had another issue.

I find it funny when that happens to me. When I add some code to 'debug' the original problem and then I just add more bugs in the debugging code. Anyway, this was the code:

examples/array_slice_not_working.pl



my $str = "root:*:0:0:System Administrator:/var/root:/bin/sh"; my @fields = split /:/, $str; $num="0,4"; my ($username, $real_name) = @fields[$num]; print "$username

"; print "$real_name

";

$ perl array_slice_not_working.pl root

Here too we start by adding use strict and use warnings.

examples/array_slice_strict.pl



use strict; use warnings; my $str = "root:*:0:0:System Administrator:/var/root:/bin/sh"; my @fields = split /:/, $str; $num="0,4"; my ($username, $real_name) = @fields[$num]; print "$username

"; print "$real_name

";

The result is more spectacular:

$ perl array_slice_strict.pl Global symbol "$num" requires explicit package name (did you forget to declare "my $num"?) at array_slice_strict.pl line 7. Global symbol "$num" requires explicit package name (did you forget to declare "my $num"?) at array_slice_strict.pl line 8. Execution of array_slice_strict.pl aborted due to compilation errors.

The error Global symbol requires explicit package name tells us that the variable $num has not been declared using my

We do that and run the script again:

examples/array_slice_warnings.pl



use strict; use warnings; my $str = "root:*:0:0:System Administrator:/var/root:/bin/sh"; my @fields = split /:/, $str; my $num="0,4"; my ($username, $real_name) = @fields[$num]; print "$username

"; print "$real_name

";

This time we get the warnings that are already familiar from the previous attempt:

$ perl array_slice_warnings.pl Scalar value @fields[...] better written as $fields[...] at array_slice_warnings.pl line 8. Argument "0,4" isn't numeric in array slice at array_slice_warnings.pl line 8. root Use of uninitialized value $real_name in concatenation (.) or string at array_slice_warnings.pl line 11.

Instead of passing a string of numbers we need to pass a list of indexes. We can either create an array of indexes manually:

my @indexes = (0, 4);

Or, if we receive the indexes as a string, we can split that string into a list of numbers:

my $num="0,4"; my @indexes = split /,/, $num;

examples/array_slice_fixed.pl



use strict; use warnings; my $str = "root:*:0:0:System Administrator:/var/root:/bin/sh"; my @fields = split /:/, $str; my $num="0,4"; my @indexes = split /,/, $num; # my @indexes = (0, 4); my ($username, $real_name) = @fields[@indexes]; print "$username

"; print "$real_name

";

Running this version will yield the expected answer:

$ perl array_slice_fixed.pl root System Administrator

Conclusion

Always use strict and use warnings in your perl code!