How to get "Var1" value of dumper in perl - perl

When i use below code then it gives output, But i want "width", "file_media_type", "file_ext" values, But I am unable to get this value in individual. I am very new with Perl Please help me!
Code
use warnings ;
use strict;
use Image::Info qw[image_info];
use Data::Dumper;
my $file = 'd:\perl\test\a.jpg';
my $info = Dumper(image_info($file));
print $info;
Output
$VAR1 = {
'width' => 45,
'file_media_type' => 'image/png',
'file_ext' => 'png',
'PNG_Chunks' => [
'IHDR',
'gAMA',
'cHRM',
'IDAT',
'IEND'
],
'Chunk-cHRM' => ' z% Çâ ·  ÇF u0 O` :ù ?o',
'PNG_Filter' => 'Adaptive',
'color_type' => 'RGB',
'height' => 20,
'Gamma' => '0.45454',
'resolution' => '1/1',
'SampleFormat' => 'U8',
'Compression' => 'Deflate'
};

image_info($file) returns a hash reference. Looking at the dump you know the keys available (the keys are strings before =>)
$info = image_info($file);
foreach my $key ( qw/width file_media_type file_ext/ ){
print "$key:$info->{$key}\n";
}

Related

How to print an element from an array which is inside the hash in perl

I'm trying to print the outputs from an API which are in multidimensional format.
use strict;
use warnings;
use Data::Dumper;
my $content={
'school_set' => 'SSET1234',
'result' => [
{
'school_name' => 'school_abc',
'display_value' => 'IL25',
'school_link' => 'example.com',
'status' => 'registerd',
'status_message' => 'only arts',
'school_id' => '58c388d40596191f',
}
],
'school_table' => 'arts_schools'
};
print "school_name is=".$content{result}[0]{school_name};
print "school_status is=".$content{result}[3]{status};
output
Global symbol "%content" requires explicit package name (did you forget to declare "my %content"?) at test8.pl line 20.
Global symbol "%content" requires explicit package name (did you forget to declare "my %content"?) at test8.pl line 21.
I have to print the outputs like below from the result.
school_name = school_abc
school_status = registered
If $content is a hash reference, you need to dereference it first. Use the arrow operator for that:
$content->{result}[0]{school_name}
The syntax without the arrow is only possible for %content.
my %content = ( result => [ { school_name => 'abc' } ] );
print $content{result}[0]{school_name};
If you want to print all the results, you have to loop over the array somehow. For example
#!/usr/bin/perl
use warnings;
use strict;
my $content = {
'result' => [
{
'school_name' => 'school_abc',
'status' => 'registerd',
},
{
'school_name' => 'school_def',
'status' => 'pending',
}
],
};
for my $school (#{ $content->{result} }) {
print "school_name is $school->{school_name}, status is $school->{status}\n";
}
Your data structure assumes an array, perhaps it would be useful to utilize loop output for the data of interest.
The data presented as hash reference and will require de-referencing to loop through an array.
Following code snippet is based on your posted code and demonstrates how desired output can be achieved.
use strict;
use warnings;
use feature 'say';
my $dataset = {
'school_set' => 'SSET1234',
'result' => [
{
'school_name' => 'school_abc',
'display_value' => 'IL25',
'school_link' => 'example.com',
'status' => 'registerd',
'status_message' => 'only arts',
'school_id' => '58c388d40596191f',
}
],
'school_table' => 'arts_schools'
};
for my $item ( #{$dataset->{result}} ) {
say "school_name is = $item->{school_name}\n"
. "school_status is = $item->{status}";
}
exit 0;
Output
school_name is = school_abc
school_status is = registerd

How to convert query string in hash in perl

I have a query string like this:
id=60087888;jid=16471827;from=advance;action=apply
or it can be like this :
id=60087888&jid=16471827&from=advance&action=apply
Now from this i want to create a hash that will have key as id and its value
I have done this
my %in;
$buffer = 'resid=60087888;jobid=16471827;from=advance;action=apply';
#pairs = split(/=/, $buffer);
foreach $pair (#pairs){
($name, $value) = split(/=/, $pair);
$in{$name} = $value;
}
print %in;
But the issue is in the query string it can be semin colon or & so how can we do this please help me
Don't try to solve it with new code; this is what CPAN modules are for. Specifically in this case, URI::Query
use URI::Query;
use Data::Dumper;
my $q = URI::Query->new( "resid=60087888;jobid=16471827;from=advance;action=apply" );
my %hash = $q->hash;
print Dumper( \%hash );
Gives
{ action => 'apply',
from => 'advance',
jobid => '16471827',
resid => '60087888' }
You've already an answer that works - but personally I might tackle it like this:
my %in = $buffer =~ m/(\w+)=(\w+)/g;
What this does is use regular expressions to pattern match either side of the equals sign.
It does so in pairs - effectively - and as a result is treated by a sequence of key-values in the hash assignment.
Note - it does assume you've not got special characters in your keys/values, and that you have no null values. (Or if you do, they'll be ignored - you can use (\w*) instead if that's the case).
But you get:
$VAR1 = {
'from' => 'advance',
'jid' => '16471827',
'action' => 'apply',
'id' => '60087888'
};
Alternatively:
my %in = map { split /=/ } split ( /[^=\w]/, $buffer );
We split using 'anything that isn't word or equals' to get a sequence, and then split on equals to make the same key-value pairs. Again - certain assumptions are made about valid delimiter/non-delimiter characters.
Check this answer:
my %in;
$buffer = 'resid=60087888;jobid=16471827;from=advance;action=apply';
#pairs = split(/[&,;]/, $buffer);
foreach $pair (#pairs){
($name, $value) = split(/=/, $pair);
$in{$name} = $value;
}
delete $in{resid};
print keys %in;
I know I'm late to the game, but....
#!/usr/bin/perl
use strict;
use CGI;
use Data::Dumper;
my $query = 'id=60087888&jid=16471827&from=advance&action=apply&blank=&not_blank=1';
my $cgi = CGI->new($query);
my %hash = $cgi->Vars();
print Dumper \%hash;
will produce:
$VAR1 = {
'not_blank' => '1',
'jid' => '16471827',
'from' => 'advance',
'blank' => '',
'action' => 'apply',
'id' => '60087888'
};
Which has the added benefit of dealing with keys that might not have values in the source string.
Some of the other examples will produce:
$VAR1 = {
'id' => '60087888',
'1' => undef,
'jid' => '16471827',
'from' => 'advance',
'blank' => 'not_blank',
'action' => 'apply'
};
which may not be desirable.
I would have used URI::Query #LeoNerd 's answer, but I didn't have the ability to install a module in my case and CGI.pm was handy.
also, you could
my $buffer = 'id=60087888&jid=16471827&from=advance&action=apply';
my %hash = split(/&|=/, $buffer);
which gives:
$hash = {
'jid' => '16471827',
'from' => 'advance',
'action' => 'apply',
'id' => '60087888'
};
This is VERY fragile, so I wouldn't advocate using it.

bioperl package Bio::Tree::Tree can't locate object method as_text

I'm trying to use as_text method from Bio::Tree::Tree I get this message: can't locate object method as_text via package Bio::Tree::Tree
I'm using the example here
Note that I tried other methods in the same package and they worked normally.
my $input = new Bio::TreeIO(-file => "bintree.nw",
-format => "newick");
my $tree = $input->next_tree;
my $tree_as_string = $tree->as_text($format);
print $tree_as_string;
The print Dumper($input) give this result:
$VAR1 = bless( {
'_bootstrap_style' => 'traditional',
'_handler' => bless( {
'_treelevel' => 0,
'_currentnodes' => [],
'_lastitem' => {
'tree' => 0,
'current' => [],
'id' => 0,
'node' => 0,
'leaf' => 0
},
'nodetype' => 'Bio::Tree::Node',
'_root_verbose' => 0,
'treetype' => 'Bio::Tree::Tree',
'_currentitems' => [],
'_nodect' => [
undef,
2,
0,
0,
0,
0,
0,
0,
0
]
}, 'Bio::TreeIO::TreeEventBuilder' ),
'_file' => 'bintree.nw',
'newline_each_node' => undef,
'internal_node_id' => 'id',
'_root_cleanup_methods' => [
sub { "DUMMY" }
],
'_flush_on_write' => 1,
'_filehandle' => \*Symbol::GEN0,
'_root_verbose' => 0,
'_print_tree_count' => 0
}, 'Bio::TreeIO::newick' );
Here is the Print Dumper ($tree)
is there a mistake ? or it's a bug ?
Thanks in advance
Your code is not working because you have not set the variable $format to anything, so the Bio::TreeIO class cannot find a class to load for the format. Try this code (it works for me):
#!/usr/bin/env perl
use strict;
use warnings;
use Bio::TreeIO;
my $usage = "$0 treefile\n";
my $infile = shift or die $usage;
my $treeio = Bio::TreeIO->new(-file => $infile, -format => 'newick');
print $treeio->next_tree->as_text('newick');
EDIT: Here is a version using your tree as the input:
#!/usr/bin/env perl
use strict;
use warnings;
use Bio::TreeIO;
my $treeio = Bio::TreeIO->new(-fh => \*DATA, -format => 'newick');
print $treeio->next_tree->as_text('newick');
__DATA__
(((A:5,B:5)90:2,C:4)25:3,D:10);
If we run this code, it prints the tree, as expected.
$ perl so18645089.pl
(((A:5,B:5)90:2,C:4)25:3,D:10);
I'm using BioPerl 1.6.901, the latest version (and the version the documentation on CPAN describes). Version 1.6.0 is very old (>5 years) and is not even on CPAN anymore. I bet if you upgrade, your troubles will disappear.

How to incorporate hash inside hash in perl?

my %book = (
'name' => 'abc',
'author' => 'monk',
'isbn' => '123-890',
'issn' => '#issn',
);
my %chapter = (
'title' => 'xyz',
'page' => '90',
);
How do I incorporate %book inside %chapter through reference so that when I write "$chapter{name}", it should print 'abc'?
You can copy the keys/values of the %book into the %chapter:
#chapter{keys %book} = values %book;
Or something like
%chapter = (%chapter, %book);
Now you can say $chapter{name}, but changes in %book are not reflected in %chapter.
You can include the %book via reference:
$chapter{book} = \%book;
Now you could say $chapter{book}{name}, and changes do get reflected.
To have an interface that allows you to say $chapter{name} and that does reflect changes, some advanced techniques would have to be used (this is fairly trivial with tie magic), but don't go there unless you really have to.
You could write a subroutine to check a list of hashes for a key. This program demonstrates:
use strict;
use warnings;
my %book = (
name => 'abc',
author => 'monk',
isbn => '123-890',
issn => '#issn',
);
my %chapter = (
title => 'xyz',
page => '90',
);
for my $key (qw/ name title bogus / ) {
print '>> ', access_hash($key, \%book, \%chapter), "\n";
}
sub access_hash {
my $key = shift;
for my $hash (#_) {
return $hash->{$key} if exists $hash->{$key};
}
undef;
}
output
Use of uninitialized value in print at E:\Perl\source\ht.pl line 17.
>> abc
>> xyz
>>

troubleshooting "pseudo-hashes are deprecated" while using xml module

I am just learning how to use perl hashes and ran into this message in perl. I am using XML::Simple to parse xml output and using exists to check on the hash keys.
Message:
Pseudo-hashes are deprecated at ./h2.pl line 53.
Argument "\x{2f}\x{70}..." isn't numeric in exists at ./h2.pl line 53.
Bad index while coercing array into hash at ./h2.pl line 53.
I had the script working earlier with one test directory and then executed the script on another directory for testing when I got this message. How do I resolve/workaround this?
Code that the error references:
use strict;
use warnings;
use XML::Simple;
use Data::Dumper;
#my $data = XMLin($xml);
my $data = XMLin($xml, ForceArray => [qw (file) ]);
my $size=0;
if (exists $data->{class}
and $data->{class}=~ /FileNotFound/) {
print "The directory: $Path does not exist\n";
exit;
} elsif (exists $data->{file}->{path}
and $data->{file}->{path} =~/test-out-00/) {
$size=$data->{file}->{size};
if ($size < 1024000) {
print "FILE SIZE:$size BYTES\n";
exit;
}
} else {
exit;
}
print Dumper( $data );
Working test case, data structure looks like this:
$VAR1 = {
'recursive' => 'no',
'version' => '0.20.202.1.1101050227',
'time' => '2011-09-30T02:49:39+0000',
'filter' => '.*',
'file' => {
'owner' => 'test_act',
'replication' => '3',
'blocksize' => '134217728',
'permission' => '-rw-------',
'path' => '/source/feeds/customer/test/test-out-00',
'modified' => '2011-09-30T02:48:41+0000',
'size' => '135860644',
'group' => '',
'accesstime' => '2011-09-30T02:48:41+0000'
'modified' => '2011-09-30T02:48:41+0000'
},
'exclude' => ''
};
recursive:no
version:0.20.202.1.1101050227
time:2011-10-01T07:06:16+0000
filter:.*
file:HASH(0x84c83ec)
path:/source/feeds/customer/test
directory:HASH(0x84c75d8)
exclude:
Data structure with seeing error:
$VAR1 = {
'recursive' => 'no',
'version' => '0.20.202.1.1101050227',
'time' => '2011-10-03T04:49:36+0000',
'filter' => '.*',
'file' => [
{
'owner' => 'test_act',
'replication' => '3',
'blocksize' => '134217728',
'permission' => '-rw-------',
'path' => '/source/feeds/customer/test/20110531/test-out-00',
'modified' => '2011-10-03T04:47:46+0000',
'size' => '121406618',
'group' => 'feeds',
'accesstime' => '2011-10-03T04:47:46+0000'
},
Test xml file:
<?xml version="1.0" encoding="UTF-8"?><listing time="2011-10-03T04:49:36+0000" recursive="no" path="/source/feeds/customer/test/20110531" exclude="" filter=".*" version="0.20.202.1.1101050227"><directory path="/source/feeds/customer/test/20110531" modified="2011-10-03T04:48:19+0000" accesstime="1970-01-01T00:00:00+0000" permission="drwx------" owner="test_act" group="feeds"/><file path="/source/feeds/customer/test/20110531/test-out-00" modified="2011-10-03T04:47:46+0000" accesstime="2011-10-03T04:47:46+0000" size="121406618" replication="3" blocksize="134217728" permission="-rw-------" owner="test_act" group="feeds"/><file path="/source/feeds/customer/test/20110531/test-out-01" modified="2011-10-03T04:48:04+0000" accesstime="2011-10-03T04:48:04+0000" size="127528522" replication="3" blocksize="134217728" permission="-rw-------" owner="test_act" group="feeds"/><file path="/source/feeds/customer/test/20110531/test-out-02" modified="2011-10-03T04:48:19+0000" accesstime="2011-10-03T04:48:19+0000" size="125452919" replication="3" blocksize="134217728" permission="-rw-------" owner="test_act" group="feeds"/></listing>
The "Pseudo-hashes are deprecated" error means you're trying to access an array as a hash, which means that either $data->{file} or $data->{file}{path} is an arrayref.
You can check the data type by using print ref $data->{file}. The Data::Dumper module may also help you to see what is in your data structure (perhaps while setting $Data::Dumper::Maxdepth = N to limit the dump to N number of levels if the structure is big).
UPDATE
Now that you are using ForceArray, $data->{file} should always point to an arrayref, which may possibly have multiple references to path. Here is a modified segment of your code to handle that. But note that the logic of the if-then-exit conditions may have to change.
if (defined $data->{class} and $data->{class}=~ /FileNotFound/) {
print "The directory: $Path does not exist\n";
exit;
}
exit if ! defined $data->{file};
# filter the list for the first file entry named test-out-00
my ( $file ) = grep {
defined $_->{path} && $_->{path} =~ /test-out-00/
} #{ $data->{file} };
exit if ! defined $file;
$size = $file->{size};
if ($size < 1024000) {
print "FILE SIZE:$size BYTES\n";
exit;
}
When using XML::Simple, the ForceArray option is one of the most important to understand, especially in cases when your input data has nested elements that can occur 1 or more times. For example:
use XML::Simple;
use Data::Dumper;
my #xml_snippets = (
'<opt> <name x="3" y="4">B</name> <name x="5" y="6">C</name> </opt>',
'<opt> <name x="1" y="2">A</name> </opt>',
);
for my $xs (#xml_snippets){
my $data = XMLin($xs, ForceArray => 0);
print Dumper($data);
}
Output:
$VAR1 = {
'name' => [ # Array ref because there are 2 <name> elements.
{
'y' => '4',
'content' => 'B',
'x' => '3'
},
{
'y' => '6',
'content' => 'C',
'x' => '5'
}
]
};
$VAR1 = {
'name' => { # No intermediate array ref.
'y' => '2',
'content' => 'A',
'x' => '1'
}
};
By activating the ForceArray option, you can direct XML::Simple to produce consistent data structures that always use the intermediate array reference, even when there is only 1 of a particular nested element. You can activate the option globally or for specific tags, as illustrated here:
my $data = XMLin($xs, ForceArray => 1 ); # Globally.
my $data = XMLin($xs, ForceArray => [qw(name foo bar)]);
First, I recommend that you use ForceArray => [qw( file )] as previously discussed. That will cause an array to be returned for file, whether there's one or more file element. This is easier to handle than having two possible formats.
As I previously indicated, the problem is that you made no provision for looping over multiple file elements. You said you wanted to exit if the file doesn't exist, so that means you want
my $found;
for my $file (#{ $data->{file} }) {
if ($file->{path} =~ m{/test-out-00\z}) {
$found = $file;
last;
}
}
die("Test file not found\n") if !$found;
... do something with file data in $found ...