novy has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, masters of perl, could you please help me out with the following problem: I've got a problem with loading the output of a UNIX command into a hash of hashes. The command in question is tapeutil -f /dev/smc0 inventory. The output looks something like this:
Slot address 1123 Slot state ...................... Normal Media present ................... Yes Robot access allowed ............ Yes Source element address valid .... Yes Media inverted .................. No Volume Tag ...................... A00401
What I'd like to do is reference each tape (volume tag field) to it's slot address since I can only work with those. I need this for a script that would load the next tape that I want automatically after the first one is full, using command tar --new-volume-script=nextvol.pl Thank you in advance...

Replies are listed 'Best First'.
Re: loading a hash of hashes from UNIX command output
by ikegami (Patriarch) on Dec 06, 2009 at 22:23 UTC

    I don't know why you need a HoH to get the next volume

    tapeutil -f /dev/smc0 inventory | perl -nle' BEGIN { $slot = shift(@ARGV); } if (/^Slot address (\d+)$/) { $ok = $slot == $1; } elsif ($ok && /^ *Volume Tag[ .]+(.*)/) { print ++($vol=$1); last; } ' 1123

    Update: I suppose you want the next volume for a specific slot. Fixed.

Re: loading a hash of hashes from UNIX command output
by GrandFather (Saint) on Dec 06, 2009 at 21:48 UTC

    So what is the (pertinent) code you have so far and what is the specific problem you are having? What does the code look like that will use the HoH?

    A very short script that takes the input data you've shown and that demonstrates what you want to achieve will help us a lot in understanding what the nature of you problem is and where you are in your Perl journey so we can give the best advice.


    True laziness is hard work
Re: loading a hash of hashes from UNIX command output
by ikegami (Patriarch) on Dec 06, 2009 at 22:44 UTC
    Or did you want the volume after highest existing volume?
    tapeutil -f /dev/smc0 inventory | perl -le' my $vol = ( sort grep /^ *Volume Tag[ .]+(.*)/, <> )[-1]; print ++$vol; '

    Your requirements are very unclear to me.

      I'll send you what I've done so far tomorrow when I get to work. Basically what I need is a script that will tell the robot to unload the running tape back to it's home slot, and load the next in the list into the drive and so on, and make sure it doesn't load the same tape more than once during the entire backup. Also after the backup is done I need to remove all the tapes that that particular backup used off the list so the backup that's next in line doesn't overwrite any of them. Since I can only tell the robot to load a tape from a slot, I'd like to be able to do something like: tapeutil -f /dev/smc0 load $slot_nr(A00401) Come to think of it maybe an ordinary hash would do, but I still don't know how to load that inventory, which has multiple lines per record into a hash, and filter out everything except Slot and Tag.

        Sounds like you want to lookup the volume for a given slot address and that you want to do that for multiple volumes during the run of the program.

        If you have the inventory in a variable:

        my %slot_lkup = reverse map /^Slot address (\d+).*\n +Volume Tag[ .]+([^\n]+)/s, split /(?<=\n)(?! )/, $inventory; ... $slot_lkup{$vol} ...

        If you have the inventory in a file handle:

        my %slot_lkup; { my $slot; while (<$fh>) { if (/^Slot address (\d+)/) { $slot = $1; } elsif (/^ *Volume Tag[ .]+([^\n]+)/) { $slot_lkup{$1} = $slot; } } } ... $slot_lkup{$vol} ...