Perl Array values show in different line without using loop - perl

Could anyone tell me how could I print values of array in different rows without using loop?
#!/usr/bin/perl -w
my #a = ('Test1','Test2','Test3');
print "#a";# output like **Test1 Test2 Test3** but i want **Test2 in next line and Test3 next to next line**
Is it Possible?

You can just do:
print join("\n", #ar);

You can set $" variable
$" = "\n";
It's probably better to do
{
local $" = "\n";
print "#ar";
}
EDIT:
according to the camel book :
$" (or the alternative $LIST_SEPERATOR) specifies the string to put between individual elements when an array is interpolated into a double-quoted string, this for the case you want to say:
print "#ar";
$, (or the alternative $OUTPUT_FIELD_SEPERATOR) specifies the string to put between individual elements when you want to print a list. It's initially empty. You can set $, for the case you want to say:
print #ar;

You can set the $, special variable to be whatever you want to separate your list elements. This should do what you want:
$, = "\n";
my #a = ('Test1','Test2','Test3');
print #a;

use map function
print #array = map{"$_\n"} #a;

Related

multidimensional array: argument isn't numeric in array element

OS: AIX
Shell: KSH
Following the accepted answer on this question I have created an multimensional array. Only, I get an error while trying to print the content of the array.
Error:
Argument "content of $pvid" isn't numeric in array element at...
The script:
#!/usr/bin/perl
use warnings;
use strict;
use Term::ANSIColor;
my #arrpvid = ();
print colored( sprintf("%-10s %9s %8s %8s %8s", 'PVID', 'AIX', 'VIO', 'VTD', 'VHOST'), 'green' ), "\n";
foreach my $pvid (`lspv | awk '{print \$2'}`) {
foreach my $hdaix (`lspv | awk '{print \$1'}`) {
chomp $pvid;
chomp $hdaix;
push #{ $arrpvid[$pvid] }, $hdaix;
}
}
print $arrpvid[0][0];
Some explanation:
Basically I want to print 5 variables of 5 different arrays next to each other. The code is written only for 2 arrays.
The content of $pvid:
00088da343b00d9b
00088da38100f93c
The content of $hdaix:
hdisk0
hdisk1
Quick Fix
Looks like you want to use a hash rather than an array, making your inner push
push #{ $arrpvid{$pvid} }, $hdaix;
Note the change from square brackets to curly braces immediately surrounding $pvid. This tells the compiler that you want %arrpvid and not #arrpvid, so be sure to tweak your my declaration as well.
At the end to print the contents of %arrpvid, use
foreach my $pvid (sort { hex $a <=> hex $b } keys %arrpvid) {
local $" = "]["; # handy trick due to mjd
print "$pvid: [#{$arrpvid{$pvid}}]\n";
}
The Data::Dumper module is quick and easy output tool.
use Data::Dumper;
$Data::Dumper::Indent = $Data::Dumper::Terse = 1;
print Dumper \%arrpvid;
More Details
You might be tempted to obtain the numeric value corresponding to each hexadecimal string in $pvid with hex as in
push #{ $arrpvid[hex $pvid] }, ...
but given the large example values in your question, #arrpvid would become enormous. Use a hash to create a sparse array instead.
Be sure that all the values of $pvid have the same padding. Otherwise, like values may not hash together appropriately. If you need to normalize, use code along the lines of
$pvid = sprintf "%016x", hex $pvid;
The problem lies in:
push #{ $arrpvid[$pvid] }, $hdaix;
The $pvid should be a numeric value like 0 or 5 and not i.e. 00088da343b00d9b

perl push many array in one array

I have many short array
#seq1 /773..1447/ #seq2 /1 2 1843..1881 1923..2001/
but i use push
push(#add, #seq1);
push(#add, #seq2);
but it shows like it combine all array into one can't get each sub-array any more
/773..1447 1 2 1843..1881 1923..2001/
when i use
$number=#add;
it shows 6, but it should be 2. Can anyone explain the reason and how to change it.
When i use for loop to add each array
for(..){
#temp= split(/,/,$_);
push(#add, \#temp);
}
Then when i print #add; it only shows memory address, How can show all data in #add
This is normal behavior, use reference to #seq1 if you want #add to be two dimensional array,
push(#add, \#seq1);
To print all values in #add you should use Data::Dumper; print Dumper \#add;
The reason is that all parameters get flattened into list when they are pushed into array, so
#a = #b = (1,2);
push(#add, #a, #b);
is same as writing
push(#add, $a[0],$a[1], $b[0],$b[1]);
Check perlref and perllol for reference.
the push command takes an ARRAY and a LIST. It is important to understand what happens here.
The first argument must be an ARRAY, the one you want to push things on. After that it expects a LIST. What this means is that this push statement provides list context to any #seq_n array - and sort of expands the array into separate elements. So all the elements of the #seq_n are being pushed onto your #add.
Since you did not want that to happen, you wanted an array that holds the separate lists - what we call in Perl a List-of-Lists - you actually wanted to push a reference to your #seq_n arrays, using the \ character.
push #add, \#seq_1, \#seq_2, . . . \#seq_n;
Now you have an array that indeed holds references to each $seq_n.
To print them neatly, each sequence on its own line, you could iterate over each
foreach my $seq (#add) {
# $seq holds a reference to a list!
my $string = join " ", #$seq; # the # dereferences the $seq
print $string, "\n";
}
but TIMTOWTDI
print map {(join " ", #$_), "\n"} #add;
Always consider the context in Perl, and try to embrace the charms of join, grep and map.

How to get sub array?

I have the code below:
#a = ((1,2,3),("test","hello"));
print #a[1]
I was expecting it to print
testhello
But it gives me 2.
Sorry for the newbie question (Perl is a bit unnatural to me) but why does it happen and how can I get the result I want?
The way Perl constructs #a is such that it is equivalent to your writing,
#a = (1,2,3,"test","hello");
And that is why when you ask for the value at index 1 by writing #a[1] (really should be $a[1]), you get 2. To demonstrate this, if you were to do the following,
use strict;
use warnings;
my #a = ((1,2,3), ("test","hello"));
my #b = (1,2,3,"test","hello");
print "#a\n";
print "#b\n";
Both print the same line,
1 2 3 test hello
1 2 3 test hello
What you want is to create anonymous arrays within your array - something like this,
my #c = ([1,2,3], ["test","hello"]);
Then if you write the following,
use Data::Dumper;
print Dumper $c[1];
You will see this printed,
$VAR1 = [
'test',
'hello'
];
Perl lists are one-dimensional only, which means (1,2,(3,4)) is automatically flattened to (1,2,3,4). If you want a multidimensional array, you must use references for any dimension beyond the first (which are stored in scalars).
You can get any anonymous array reference with bracket notation [1,2,3,4] or reference an existing array with a backslash my $ref = \#somearray.
So a construct such as my $aref = [1,2,[3,4]] is an array reference in which the first element of the referenced array is 1, the second element is 2, and the third element is another array reference.
(I find when working with multidimensional arrays, that it's less confusing just to use references even for the first dimension, but my #array = (1,2,[3,4]) is fine too.)
By the way, when you stringify a perl reference, you get some gibberish indicating the type of reference and the memory location, like "ARRAY(0x7f977b02ac58)".
Dereference an array reference to an array with #, or get a specific element of the reference with ->.
Example:
my $ref = ['A','B',['C','D']];
print $ref; # prints ARRAY(0x001)
print join ',', #{$ref}; # prints A,B,ARRAY(0x002)
print join ',', #$ref; # prints A,B,ARRAY(0x002) (shortcut for above)
print $ref->[0]; # prints A
print $ref->[1]; # prints B
print $ref->[2]; # prints ARRAY(0x002)
print $ref->[2]->[0]; # prints C
print $ref->[2][0]; # prints C (shortcut for above)
print $ref->[2][1] # prints D
print join ',', #{$ref->[2]}; # prints C,D
I think you're after an array of arrays. So, you need to create an array of array references by using square brackets, like this:
#a = ([1,2,3],["test","hello"]);
Then you can print the second array as follows:
print #{$a[1]};
Which will give you the output you were expecting: testhello
It's just a matter of wrong syntax:
print $a[1]

Using map on an array with sprintf

I have the following code:
my #some_range = (6..10);
my #some_range_new = map(sprintf("I%03d ", $_), \#some_range);
say join(' ', #some_range_new)
I would expect the output to be:
I006 I007 I008 I009 I010
but instead I get:
275738152
Why?
Note: I know that I can do my #some_range_new = ("I006".."I010"), but I am trying to learn to use map in combination with sprintf
You use a reference to #some_range in your map statement. I'm not sure why you thought that would work.
The correct way is
map sprintf("I%03d", $_), #some_range;
In short, just remove the backslash and your code will work.
The reason it fails is that \#some_range will be interpreted as a number by %d. When an array reference is interpreted as a number, it evaluates to the address of the referenced array. For example:
$ perl -lwe '#a=1..10; $x = \#a; print $x; printf "I%03d", $x'
ARRAY(0x468c18)
I4623384

perl, saving the command line option

I have this perl script and it takes in arguments using the getoption package.
Is there an easy way to document what was the exact command the user used to execute?
I would like to document into a log file.
Gordon
Use $0 and #ARGV together:
my $full_command = join(' ', $0, #ARGV);
or you can simply
my $full;
BEGIN { $full = "$0 #ARGV" }
#
print "log: $full\n";
form the perlvar
$LIST_SEPARATOR
$"
When an array or an array slice is
interpolated into a double-quoted
string or a similar context such as
/.../ , its elements are separated by
this value. Default is a space. For
example, this:
print "The array is: #array\n";
is equivalent to this:
print "The array is: " . join($", #array) . "\n";