[colug-432] Using Perl's Data::Walk

Richard Hornsby richardjhornsby at gmail.com
Tue Jun 18 01:15:10 EDT 2013


I decided that Safari's "block cookies from 3rd parties and advertisers" wasn't good enough.  And yet, cookies are useful, so I don't want to wipe them all out.  It occurred to me that the valid cookies I would want to keep might be determined by examining my bookmarks (perhaps also History).  Step 1, then is to get a hash table of domains I have bookmarks for.  Safari stores the bookmarks in a plist format.  Perl's Data::Plist can handle this pretty easily.

If I use Dumper to print the plist structure, I get something that looks like so:

---
$VAR1 = {
          'WebBookmarkFileVersion' => 1,
          'Children' => [
                        {
                          'WebBookmarkIdentifier' => 'History',
                          'WebBookmarkUUID' => '3D97D674-348B-47EC-9066-86DCC1439C8A',
                          'WebBookmarkType' => 'WebBookmarkTypeProxy',
                          'Title' => 'History'
                        },
                        {
                          'Children' => [
                                        {
                                          'URLString' => 'http://www.apple.com/',
                                          'WebBookmarkUUID' => '1B96FA5F-46AE-476C-969D-4234C45F7E38',
...
etc.
---

Pretty easy to read.  The bit that I'm trying to extract is the value from the hash key URLString, inside the array, inside the hash Children, etc.  Data::Walk seems like the right tool.  I'm struggling with is using Data::Walk and not understanding what it is doing.

http://search.cpan.org/~guido/Data-Walk-1.00/lib/Data/Walk.pm

It seems to be not understanding to stop tearing the data structure apart.  Data::Walk seems to be saying that both URLString and the actual URL are both hashes, but then presents them as scalars to Dumper, based on print output from the wanted callback:

[:6:HASH(0x7f89cabee360)]
$VAR1 = 'URLString';
[:6:HASH(0x7f89cabee360)]
$VAR1 = 'http://www.apple.com/';

The '6' is $Data::Walk::depth, and the 'HASH(…)' is $Data::Walk::container.  I'm not sure that I can be confident that 6 is the correct depth always, so I can't depend on a magic value for the depth.

What I'd really like to do is simple: as I'm processing the data structure, determine if I have a hash, and if there is a key URLString, grab the value.

I know how to check a hash for a key using exists under normal conditions (use this all the time as my goto reference http://www.cs.mcgill.ca/~abatko/computers/programming/perl/howto/hash/), but with Data::Walk I'm having a hard time because Data::Walk is turning "URLString" into a scalar.  Again inside the callback, this does not seem to work, but instead throws errors that I can't ask for the keys out of a scalar deref(?)

if ($Data::Walk::type eq 'HASH') {
     print Dumper(keys $_);
}

-> Type of arg 1 to keys must be hash or array (not scalar dereference) at ./cookie_cleanup.pl line 36, near "$_)"


I love Perl, but I've always struggled with references and other complex Perl data structures.  Usually feels like playing whack-a-mole with the code until I get it right.  I understand basic concepts like values vs references (i.e. in PHP, Java, etc), but the way Perl does it, and how to get at them confuses the crap out of me.

Any thoughts?  Maybe I'm going about the Perl all wrong?

thanks
-rick


More information about the colug-432 mailing list