newperluser2013 has asked for the wisdom of the Perl Monks concerning the following question:
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.
recurse_hash(\%$decoded_json_obj,"@keylist");
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
|
---|