Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Perl script to comment out lines in named.conf file

by firewall00 (Acolyte)
on Oct 04, 2007 at 21:40 UTC ( [id://642777]=perlquestion: print w/replies, xml ) Need Help??

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

hello all

i want to make a perl script that : - 1.) ask user to enter the domain name which is in the zone that will be commented .
2.) search in the named.conf file for a multi line string including domain that entered by the user
2.) comment out the whole zone that including the matching domain name , from the empty line before the zone name and then to a five lines "to comment all the zone part .
here is a sample of that file :

zone "dontchangethisdomain.com" {
type master;
file "/somepath/to/dontchangethisdomain.com";
notify yes;
}
zone "mydomain.com" {
type master;
file "/path/to/zone/mydomain.com";
notify yes;
}
zone "leavethisalonetoo.com" {
type master;
file "/other/path/to/leavethisalonetoo.com";
notify yes;
}
i worte that code and i cannot figure out what to do next
#!/usr/bin/perl -w use strict; print " please enter the domain name: "; my $targetdomain = <STDIN>; chomp $targetdomain; my $file = "/home/blackice/hello"; open HAN,$file || die "error opening file: $!"; while (<HAN>) { if ( $file =~ m/\n(.?)zone "$targetdomain" \{\n(.*)type(.*);\n(.*)file(.*);\n(.*)notify(.*);\ n(.?)\}/is)

first: i asked the user to enter the domain for the zone that will be commented .
then i open the file by a file handler and search with a matching string for a matching zone that include tha $targetdomain which is
entered by the user .
i just finished at here but how i can comment the lines of the zone starting from the empty line before the zone name till the last '}'
without affecting other zones ...
sorry for the long thread and any help will be appreciated :)

Replies are listed 'Best First'.
Re: Perl script to comment out lines in named.con file
by shmem (Chancellor) on Oct 04, 2007 at 22:55 UTC
    Good start, but are all your zone definitions that uniform?

    You might have some that read

    zone "10.in-addr.arpa" { type forward; forwarders { 10.1.2.3; 10.1.2.4; 10.1.2.5; }; };

    There are, as always, many ways to do it - one:

    my $comment = 0; my $block = 0; while (<HAN>) { /^zone\s+"$targetdomain"/ and $comment++; if($comment) { $block += () = /(\{)/g; # add the number of { matches t +o $block s!^!// ! if $comment && $block; $block -= () = /(\})/g; # substract the number of } mat +ches $comment = 0 unless $block; } print; }

    That will work only if the opening curly after a zone declaration is on the same line.

    BTW, you need a semicolon after every closing curly in your zone file ( }; ).

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      thanks for you replay :)
      but i want to know what are the function of two variables $comment ,, $block
      please explain me carefully cuz iam newbie :) .
      and if i want to instead of printing the commented zone in the shell
      i want how to make that inside the file affecting the matched zone only
      and iam thankful for you
        • $comment is a switch, which is turned on when the sought zone is found, and turned of if the associated block is processed. If $comment is true (i.e. not '0' and not ''), the current line is commented out.
        • $block is a counter for the curly bracket level. It is increased with each opening bracket, and decreased with each closed bracket. If the last closing bracket of the zone block is found, it is zero, we are done and can unset $comment.

        The empty () in the assignments force list context on the right hand side (global match), so we get all matches; the left hand side is a scalar ($block), so we get the count of those matches: a list evaluated in scalar context returns the number of elements of the list.

        To edit the file, it makes sense to backup the file and write it:

        #!/usr/bin/perl -w use strict; print " please enter the domain name: "; my $targetdomain = <STDIN>; chomp $targetdomain; my $file = "/home/blackice/hello"; rename $file, "$file.bak" or die "Can't rename file '$file': $!\n"; open my $in, '<', "$file.bak" or die "Can't read file '$file': $!\n"; open my $out, '>', $file or die "Can't write file '$file': $!\n"; my $comment = 0; my $block = 0; while(<$in>) { if (/^zone\s+"$targetdomain"/) { $comment++; $block += () = /(\{)/g; print $out '// '.$_; next; } if($comment) { $block += () = /(\{)/g; s!^!// ! if $comment or $block; $block -= () = /(\})/g; $comment = 0 unless $block; } print $out $_; }

        This version works also with zone entries where the opening curly is on the next line:

        zone "foo" { type "master"; ... };

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Perl script to comment out lines in named.con file
by GrandFather (Saint) on Oct 04, 2007 at 22:58 UTC

    For a start you have to create a new instance of the file. Perl helps by facilitating inplace editing of files using @ARGV, $^I and while (<>) {...} magic.

    The other less common element Perl used in this code is the scalar context range operator ...

    use strict; use warnings; open OUTFILE, '>', 'delme.txt'; print OUTFILE <<TEXT; zone "dontchangethisdomain.com" { type master; file "/somepath/to/dontchangethisdomain.com"; notify yes; } zone "mydomain.com" { type master; file "/path/to/zone/mydomain.com"; notify yes; } zone "leavethisalonetoo.com" { type master; file "/other/path/to/leavethisalonetoo.com"; notify yes; } TEXT close OUTFILE; my $targetdomain = 'mydomain.com'; @ARGV = ('delme.txt'); $^I = '.bak'; while (<>) { print "#" if m/^zone "\Q$targetdomain\E" {/ .. m/^}/; print; }

    Generates delme.txt containing:

    zone "dontchangethisdomain.com" { type master; file "/somepath/to/dontchangethisdomain.com"; notify yes; } #zone "mydomain.com" { #type master; #file "/path/to/zone/mydomain.com"; #notify yes; #} zone "leavethisalonetoo.com" { type master; file "/other/path/to/leavethisalonetoo.com"; notify yes; }

    Perl is environmentally friendly - it saves trees
      thanks for your help
      put there isn't any way to edit in the file locally without making instance ? .

        You have to insert characters. Think about what that entails in terms of manipulating the file image on the hard disk. Every character after the inserted character has to be moved.

        There are modules like Tie::File which hide the details from you and expend a great amount of effort to make the process efficient, but at the end of the day every character in the file after the first character that is inserted has to be rewritten.


        Perl is environmentally friendly - it saves trees
Re: Perl script to comment out lines in named.conf file
by graff (Chancellor) on Oct 05, 2007 at 01:26 UTC
    If the string that marks the end of a zone block is really consistent and distinctive -- e.g. every block ends with a line whose first character is "}", and this is only found at the end of a block -- you can use the input record separator variable "$/" to make this much easier.
    #!/usr/bin/perl use strict; ( @ARGV == 2 and -f $ARGV[0] ) or die "Usage: $0 input.file domain.to.comment.out\n"; my ( $in_file, $rem_domain ) = @ARGV; open IN, "<", $in_file or die "$in_file: $!"; open OUT, ">", "$in_file.new" or die "$in_file.new: $!"; $/ = "\n}"; # input record separator is line-initial "}" while (<IN>) { # $_ contains a whole zone block if (/\W$rem_domain\W/) { s/^/#/; # add initial comment to block s/\n/\n#/g; # add comment after each "\n" } print OUT; }
    The number of zone blocks that will be commented out in the file depends on what the user provides as the second command line arg on the script. I would recommend that you not rename the output to replace the input file as part of this script: the user should have a chance to confirm that the output file was changed as intended -- e.g. that there wasn't a mistake in the second command line arg.

    (It could happen that someone hits the "Enter" key too soon, and comments all zone blocks that match an unintended substring.) BTW, this approach is also an easy way to uncomment a chosen block, in case you ever need that sort of tool.

    (update: forgot mention: look up $/ in perlvar)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://642777]
Approved by almut
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (4)
As of 2024-04-18 21:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found