Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

Hi Monks I am very new to perl and was hoping you could help me with how to do the following. I am trying to recursively traverse a rather large complex data structure which is a hash of hashes. While I am traversing this data structure I want to search for keys with a certain name and then once I have all the keys which make up one line of output I then want to print that line with all the corresponding values. I want to then keep traversing through this data structure and then find the next line of keys that match the keylist I am looking for and then print out the whole line of output. I want to keep doing this until I reach the bottom of the data structure. So I have the following hash of hashes with the keys %export_name, %filer_device, %filer_volume, %mount_acl, %mount_group, %mount_opts, and %mount_user. I am able to parse this and grab all these keys and put them into a list called @keylist.

"nfs" => { "%comment" => "Properties for an NFS mount definition", "%export_name" => { "%type" => "path" }, "%filer_device" => { "%type" => "string" }, "%filer_volume" => { "%type" => "path" }, "%mount_acl" => { "%type" => "integer" }, "%mount_group" => { "%type" => "string" }, "%mount_opts" => { "%type" => "string" }, "%mount_user" => { "%type" => "string" } }

Now what I have is this really big complex data structure which I want to recursively parse and look for the existance of all the keys in @keylist and print the values. I need to find all of the keys; %export_name, %filer_device, %filer_volume, %mount_acl, %mount_group, %mount_opts, and %mount_user before I can print a line of output as all these are needed to fully define an nfs mount point. There are hundreds of nfs mount points defined in this data structure and I need to print out a line of output in the following format for each and every one thats found: %export_name:%filer_device:%filer_volume:%mount_acl:%mount_group:%mount_user:%mount_opts This is a small sample of this very large data structure I am trying to parse:

{ "%name": "Global Central Configuration file", "%description": "A representation of nfs mount points for dev mach +ines", "%schema": "schema.conf", "@dev": { "home_nfs": { "%default": { "%mount_opts": "nfsvers=3,timeo=600,retrans=2", "%mount_user": "root", "%mount_group": "root", "%mount_acl": "0755" }, "%comment": "----Home NFS Directories----", "home-lnk-mpt": { "%export_name": "/links", "%filer_device": { "@west": "nydevnfs_links", "@ridge": "rnap7750-s" }, "%filer_volume": { "@west": "/vol/links", "@ridge": "/vol/links_c" } }, "home7_mpt": { "%export_name": "/home7", "%filer_device": { "@west": "nydevnfs_home7", "@ridge": "rnap7751-s" }, "%filer_volume": { "@west": "/vol/home7", "@ridge": "/vol/home7_c" } }, "home8_mpt": { "%export_name": "/home8", "%filer_device": { "@west": "nydevnfs_home2", "@ridge": "rnap2114-s" }, "%filer_volume": { "@west": "/vol/home2", "@ridge": "/vol/home2_c" } },

The following is my attempt of writing a recursive sub routine to parse this large data structure but I just cant work out how to get it to do what I want

sub recurse_hash { my($hash,@findkeys) = @_; foreach (sort keys %{$hash}) { my $value = $hash->{$_}; if (ref($value) eq 'HASH') { recurse_hash($value,@findkeys); } for my $key (@findkeys) { if ($key eq $_) { print "$_ = $value\n"; } } } }

I am calling this subroutine like this but I can't get it to accept passing @keylist to it.


If I hardcode the key names like so it doesn't error and prints all all the corresponding values but they are all on different lines and don't match up.

recurse_hash(\%$decoded_json_obj,"%export_name","%filer_device","%file +r_volume","%mount_acl","%mount_group","%mount_opts");

I am not allowed to hardcode the key names as args to this subroutine. I need to pass in a list of keys defined in @keylist

Using the small sample of this large data structure I have shown I am trying to print lines in the following format.

/links:nydevnfs_links:/vol/links:0755:root:root:nfsvers=3,timeo=600,re +trans=2 /links:rnap7750-s:/vol/links_c:0755:root:root:nfsvers=3,timeo=600,retr +ans=2 /home7:nydevnfs_home7:/vol/home7:0755:root:root:nfsvers=3,timeo=600,re +trans=2 /home7:rnap7751-s:/vol/home7_c:0755:root:root:nfsvers=3,timeo=600,retr +ans=2 /home8:nydevnfs_home2:/vol/home2:0755:root:root:nfsvers=3,timeo=600,re +trans=2 /home8:rnap2114-s:/vol/home2_c:0755:root:root:nfsvers=3,timeo=600,retr +ans=2

I mustn't hardcode any references to any mount point names, filer device/volumes names etc. I purely have to parse this data structure and at each level look to see if any of the keys in @keylist exist if they do then store the value until I have values for each key in that list and can then print a line of output, and then continue doing the same throughout parsing the rest of the data structure printing a line of output for each mount point.

Please can you help me with the above? I have spent so much time trying to do this but I just cant seem to get it to work

In reply to Traversing a complex data structure searching for certain keys and printing their values by newperluser2013

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others pondering the Monastery: (8)
    As of 2018-06-25 11:08 GMT
    Find Nodes?
      Voting Booth?
      Should cpanminus be part of the standard Perl release?

      Results (126 votes). Check out past polls.