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

I have an output file that has hosts and lists of NFS share sources per hosts.

I need to produce a list of hosts per NFS share. So I think it will be a hash of arrays with they keys being the share names?

here is a snippet of the data:

ok: [cgva1lbpmor001m] => { "result.stdout_lines": [ "SOURCE FSTYPE SIZE USED AVAIL USE% TA +RGET", "kmhpemcfspa21:/oracle_depot nfs 130.1G 77.2G 52.9G 59% /e +xport/oracle", "kmhpemcfspa21:/oracle_dump nfs 11.5T 1.8T 9.7T 16% /e +xport/oracle_dump" ] }

I can easily create the hash of shares but not sure how to seek back up once a share is found and add the host to an array and add to the hash

This is all I have, I am stuck.

my $export; my %exports; open(OUT, "<", "$OUTF") or die "cant open file: $!"; while ( my $line = <OUT>) { next unless $line =~ /nfs/; chomp $line; ($export = $line) =~ s/\s+"(.*)\s+nfs.*/$1/; $export =~ s/\s+//g; $exports{$export} = 1; }

Thanks for any help

Replies are listed 'Best First'.
Re: File Parsing Question
by hippo (Archbishop) on Apr 06, 2021 at 15:31 UTC

    To do it in one pass you can use this algorithm:

    1. Read one line
    2. If it is a host line, extract the hostname and store it in a scalar variable. Go to 1.
    3. If it is not an nfs line, go to 1
    4. Extract the share from the line.
    5. If there is no entry in your hash for that share, create one which is an arrayref with the current host as its only member. Go to 1.
    6. Append the current host to the existing arrayref in the hash value for the current share. Go to 1.

    🦛

      Thanks, I thought about going this route and working on that now..

Re: File Parsing Question
by choroba (Cardinal) on Apr 06, 2021 at 16:15 UTC
    I'm not sure I understand what should be the key and what should be the value, so tweak this to your needs:
    #! /usr/bin/perl use warnings; use strict; my %source; my $host; while (<>) { if (/^ok: \[(.*)\] => \{/) { $host = $1; } elsif (/^\s+"(\S+)\s+nfs\s/) { push @{ $source{$1} }, $host; # Or maybe # push @{ $source{$host} }, $1; } } use Data::Dumper; print Dumper \%source;
    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      yes close to what I am looking for and the algorithm suggested by "Hippo". I will work on and test in a bit..
Re: File Parsing Question
by neptuna (Acolyte) on Apr 06, 2021 at 19:21 UTC
    Thank You hippo and choroba!. Works now
    my $share; my %exports; my $host; while ( my $line = <DATA>) { chomp $line; if ( $line =~ /^ok:\s+\[/ ) { ($host = $line) =~ s/ok:\s+\[(.*)\].*/$1/s; } if ($line =~ /nfs/) { ($share = $line) =~ s/\s+"(.*)\s+nfs.*/$1/; $share =~ s/\s+//g; push @{ $exports{$share} }, $host; } } for my $key ( keys %exports ) { print "$key: ", join(",", @{ $exports{$key} }), "\n" }
Re: File Parsing Question
by tybalt89 (Monsignor) on Apr 06, 2021 at 16:31 UTC

    One way to "back up" :)

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11130900 use warnings; local $_ = <<END; ok: [cgva1lbpmor001m] => { "result.stdout_lines": [ "SOURCE FSTYPE SIZE USED AVAIL USE% TA +RGET", "kmhpemcfspa21:/oracle_depot nfs 130.1G 77.2G 52.9G 59% /e +xport/oracle", "kmhpemcfspa21:/oracle_dump nfs 11.5T 1.8T 9.7T 16% /e +xport/oracle_dump" ] } ok: [otherhost] => { "result.stdout_lines": [ "SOURCE FSTYPE SIZE USED AVAIL USE% TA +RGET", "kmhpemcfspa21:/oracle_dump nfs 11.5T 1.8T 9.7T 16% /e +xport/oracle_dump" ] } ok: [thirdhost] => { "result.stdout_lines": [ "SOURCE FSTYPE SIZE USED AVAIL USE% TA +RGET", "kmhpemcfspa21:/oracle_other nfs 11.5T 1.8T 9.7T 16% /e +xport/oracle_dump" "kmhpemcfspa21:/oracle_depot nfs 130.1G 77.2G 52.9G 59% /e +xport/oracle", ] } END my %hostspershare; while( /"(\S+)\s+nfs\s/g ) { my $share = $1; $` =~ /.*ok: \[(\S+?)\]/s and push @{ $hostspershare{$share} }, $1; } use Data::Dump 'dd'; dd \%hostspershare;

    Outputs:

    { "kmhpemcfspa21:/oracle_depot" => ["cgva1lbpmor001m", "thirdhost"], "kmhpemcfspa21:/oracle_dump" => ["cgva1lbpmor001m", "otherhost"], "kmhpemcfspa21:/oracle_other" => ["thirdhost"], }
Re: File Parsing Question
by perlfan (Parson) on Apr 06, 2021 at 17:59 UTC
    That looks like the output of df? Would it be better to just inspect /etc/fstab. Checkout Sys::Filesystem.