http://www.perlmonks.org?node_id=995693


in reply to Bind zone file search

Perhaps the following will offer some direction:

use strict; use warnings; my $directory = './zones'; my %zones = getZoneHash($directory); print "$_ -> $zones{$_}\n" for keys %zones; sub getZoneHash { my ($dir) = @_; my %hash; local $/; for my $file ( grep -f, <"$dir/*"> ) { open my $fh, '<', $file or die $!; my $data = <$fh>; close $fh; $hash{$1} = $2 if $data =~ /zone\s+"([^"]+)".+masters\s+{\s*([^}\s]+)\s*}/s +; } Kg return %hash; }

There are three files in the directory zones, and each contains only one of the following zone stanzas:

zone "zone.com" { type slave; file "path/to/db.zone"; masters {ip.add.ress.here}; }; zone "cnn.com" { type slave; file "path/to/db.zone"; masters { cnn.add.ress.here }; }; zone "perlmonks.org" { type slave; file "path/to/db.zone"; masters { ip.perlmonks.ress.here }; };

Output:

cnn.com -> cnn.add.ress.here perlmonks.org -> ip.perlmonks.ress.here zone.com -> ip.add.ress.here

The subroutine getZoneHash takes a directory parameter, and then opens, reads, and captures the zone info and masters ip address of the zone stanza in each file in that directory, building and returning a hash.

The capturing regex:

/zone\s+"([^"]+)".+masters\s+{\s*([^}\s]+)\s*}/s ^ ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | | | | | | | | | | + - Treat string as sin +gle line | | | | | | | + - 0+ whitespaces | | | | | | + - Match anything that's not } o +r a whitespace | | | | | + - 0+ whitespaces | | | | + - 1+ whitespaces | | | + - End quotation | | + - Match anything that's not a " | + - Begin quotation + - 1+ whitespaces

Hope this helps!

Replies are listed 'Best First'.
Re^2: Bind zone file search
by ranceh (Novice) on Sep 26, 2012 at 13:27 UTC

    This has real promise, Thanks much.

      You're welcome much!

Re^2: Bind zone file search
by ranceh (Novice) on Sep 26, 2012 at 14:53 UTC

    What version of perl did you use?

    This code does not generate any errors, but does not generate output.

      Hi, ranceh

      Am using v5.16, but there's nothing in the code that would prevent its execution by much earlier versions, so I suspect the issue is something else. Try the following change to the subroutine:

      use strict; use warnings; my $directory = './zones'; my %zones = getZoneHash($directory); print "$_ -> $zones{$_}\n" for keys %zones; sub getZoneHash { my ($dir) = @_; my %hash; my @files = grep -f, <"$dir/*"> or die "Problem getting filenames in $dir/: $!"; local $/; for my $file (@files) { open my $fh, '<', $file or die $!; my $data = <$fh>; close $fh; $hash{$1} = $2 if $data =~ /zone\s+"([^"]+)".+masters\s+{\s*([^}\s]+)\s*}/s +; } return %hash; }

      Now there's a check for file names being read from the desired directory. The script will die with a message if none were read.

      If you're still getting the same results, temporarily place the following just below the close $fh; line:

      print $data; exit;

      You should see a zone stanza that the regex would process. If not, the next step would be to figure out why the file contents are not being read into $data.

        I think I found the problem.

        I modified your regex slightly in the beginning it starts with "/^zone..."

        I found after posing this question last night that a few of the zone files have stanzas commented out.

        The ^ in combination with the change to $/ seem to conflict with each other.

        I think it would be easier to add a not part to the regex before zone so that what is before zone is not a comment character identifier.