in reply to Matching array elements against file

G'day Mark.Allan,

There are a number of issues with what you posted. One or more of these may be the cause of your problems. You'll need to adjust your problem description and/or data and/or expected output as described here:

If you copy and paste your code and data, we will see exactly what you're seeing. Trying to make multiple guesses as to what is and isn't a typo is both annoying and error-prone. Please bear this in mind with any future posts.

I believe this code should be close to what you want. You may need to make changes where the assumptions and guesses I've documented are incorrect.

#!/usr/bin/env perl use strict; use warnings; my @checks = ( 'server=bar116aix,bar117aix:FS=/tmp', 'server=cvmfsser1, cvmfsser2:FS=/opt/apps', 'server=cvmfsser3::FS=/opt/apps', 'FS=/bar/cut/data03:NO', 'server=baraix665, baraix666, baraix667:FS=/data/hp/feeds', 'server=vmdprd:FS=/opt/tuxedo', 'server=testserver1:FS=/data/repository', ); my %data; while (<DATA>) { my ($server, $fs) = (split /::/)[0, 1]; $fs = canonicalise_fs($fs); $data{both}{join '::' => $server, $fs} = undef; $data{server}{$server} = undef; $data{fs}{$fs} = undef; } for (@checks) { print "'$_',\t"; my $server = /server=([^:]+)/ ? $1 : ''; my $fs = /FS=([^:]+)/ ? $1 : ''; $fs = canonicalise_fs($fs); if (exists $data{both}{join '::' => $server, $fs}) { print ''; } elsif (exists $data{server}{$server} or exists $data{fs}{$fs}) { print 'PART '; } else { print 'NO '; } print "MATCH\n"; } sub canonicalise_fs { my $fs = shift; $fs .= '/' unless length $fs and $fs =~ /\/$/; return $fs; } __DATA__ vmaprd::/opt/vmaprd/application::intel vmclprd::/opt/vmclprd/apps/oracle::db_support vmdprd::/opt/vmdprd/db2::db_support cvmfsser1::/opt/apps/::app_support cvmfsser3::/opt/apps/::app_support d87ser1::/opt/db2ese::db_support aix5server::/bar/cut/data03::aix_sup linuxvm001::/bar/cut/data04::linux_sup

Output:

'server=bar116aix,bar117aix:FS=/tmp', NO MATCH 'server=cvmfsser1, cvmfsser2:FS=/opt/apps', PART MATCH 'server=cvmfsser3::FS=/opt/apps', MATCH 'FS=/bar/cut/data03:NO', PART MATCH 'server=baraix665, baraix666, baraix667:FS=/data/hp/feeds', NO MATC +H 'server=vmdprd:FS=/opt/tuxedo', PART MATCH 'server=testserver1:FS=/data/repository', NO MATCH

-- Ken

Replies are listed 'Best First'.
Re^2: Matching array elements against file
by Mark.Allan (Sexton) on Jan 25, 2014 at 09:45 UTC

    Hi Ken, cutting and pasting the whole array and file would of been two large so I just tried to create snippets of the data which included all scenarios of possibilities. You are correct, the data source was sloppy I appologies.

    After observing your code (and thanks for the assistance) and digesting your points. Point 1 is a typo, correct. Point 2 the data was correct, there could be cases where server= is a missing attribute

    Point 3 you're right

    'server=cvmfsser3::FS=/opt/apps'

    This should be single :

    Your code is nearer enough what I need but one thing seems to be throwing it out at present

    'server=cvmfsser1, cvmfsser2:FS=/opt/apps',

    even if two servers appear as comma seperated, this should indeed part match but against FS and Server (server being that there is one of the two in the comma seperated list whihc exist in the file. Your code part matches against the fileystem but would not part match against the server if the filesystem didnt exist

    cvmfsser1::/opt/apps/::app_support cvmfsser3::/opt/apps/::app_support
    . As you can see in the data output, it is only showing up as a part match against the fileysstem. If the filesystem didnt exist, Id need to to part match against
    'server=cvmfsser1

    I hope I have explained myself well enough. Thanks in advance

      This seems to be yet another problem with your description.

      Perhaps 'server=' would be better as 'servers='. You could then split its value on '/,\s*/' and then treat these 3 elements:

      'server=bar116aix,bar117aix:FS=/tmp', 'server=cvmfsser1, cvmfsser2:FS=/opt/apps', 'server=baraix665, baraix666, baraix667:FS=/data/hp/feeds',

      as if they were these 7 elements:

      'server=bar116aix:FS=/tmp', 'server=bar117aix:FS=/tmp', 'server=cvmfsser1:FS=/opt/apps', 'server=cvmfsser2:FS=/opt/apps', 'server=baraix665:FS=/data/hp/feeds', 'server=baraix666:FS=/data/hp/feeds', 'server=baraix667:FS=/data/hp/feeds',

      Here I'm making further assumptions:

      • "server" in ARRAY has a different meaning to "server" in FILE:
        • ARRAY: one or more servers
        • FILE: exactly one server
      • Records in FILE never look like: "bar116aix,bar117aix::/tmp::team_name"

      -- Ken