问题
I'm playing a bit with the Net::Amazon::EC2 libraries, and can't find out a simple way to print object properties:
This works:
my $snaps = $ec2->describe_snapshots();
foreach my $snap ( @$snaps ) {
print $snap->snapshot_id . " " . $snap->volume_id . "\n";
}
But if I try:
print "$snap->snapshot_id $snap->volume_id \n";
I get
Net::Amazon::EC2::Snapshot=HASH(0x4c1be90)->snapshot_id
Is there a simple way to print the value of the property inside a print?
回答1:
Not in the way you want to do it. In fact, what you're doing with $snap->snapshot_id is calling a method (as in sub). Perl cannot do that inside a double-quoted string. It will interpolate your variable $snap. That becomes something like HASH(0x1234567) because that is what it is: a blessed reference of a hash.
The interpolation only works with scalars (and arrays, but I'll omit that). You can go:
print "$foo $bar"; # scalar
print "$hash->{key}"; # scalar inside a hashref
print "$hash->{key}->{moreKeys}->[0]"; # scalar in an array ref in a hashref...
There is one way to do it, though: You can reference and dereference it inside the quoted string, like I do here:
use DateTime;
my $dt = DateTime->now();
print "${\$dt->epoch }"; # both these
print "@{[$dt->epoch]}"; # examples work
But that looks rather ugly, so I would not recommend it. Use your first approach instead!
If you're still interested in how it works, you might also want to look at these Perl FAQs:
- What's wrong with always quoting "$vars"?
- How do I expand function calls in a string?
From perlref:
Here's a trick for interpolating a subroutine call into a string:
print "My sub returned @{[mysub(1,2,3)]} that time.\n";The way it works is that when the @{...} is seen in the double-quoted string, it's evaluated as a block. The block creates a reference to an anonymous array containing the results of the call to mysub(1,2,3) . So the whole block returns a reference to an array, which is then dereferenced by @{...} and stuck into the double-quoted string. This chicanery is also useful for arbitrary expressions:
print "That yields @{[$n + 5]} widgets\n";Similarly, an expression that returns a reference to a scalar can be dereferenced via ${...} . Thus, the above expression may be written as:
print "That yields ${\($n + 5)} widgets\n";
回答2:
$snap->volume_id is not a property, it is a method call. While you could interpolate a method call inside a string, it is exceedingly ugly.
To get all the properties of an object you can use the module Data::Dumper, included with core perl:
use Data::Dumper;
print Dumper($object);
回答3:
Stick with the first sample you showed. It looks cleaner and is easier to read.
回答4:
I'm answering this because it took me a long time to find this and I feel like other people may benefit as well.
For nicer printing of objects use Data::Printer and p():
use DateTime;
use Data::Printer;
my $dt = DateTime->from_epoch( epoch => time );
p($dt);
回答5:
The problem is that $snap is being interpolated inside the string, but $snap is a reference. As perldoc perlref tells us: "Using a reference as a string produces both its referent's type, including any package blessing as described in perlobj, as well as the numeric address expressed in hex."
In other words, within a string, you can't dereference $snap. Your first try was the correct way to do it.
回答6:
The PERL translator has limited depth perception within quotes. Removing them should solve the problem. Or just load the real values into a simple variable that you can print within the quotes. Might need to do that if you have objects which contain pointers to other objects:
SwissArmyChainSaw =/= PureMagic:
print("xxx".$this->{whatever}."rest of string\n");
回答7:
I agree with most comment, stick to concatenation for easy reading. You can use
say
instead of print to spare of using the "\n".
来源:https://stackoverflow.com/questions/13239515/perl-printing-object-properties