2

For reasons I won't go into here, I need to make a copy of an old CentOS 5.10 server's named.conf file and perform some text manipulation on the copy. The final result should consolidate each zone's info into a single, separate line. Plus, I need to script it so it can be run as a cron job. Here's an example of what I'm starting with:

zone "." {
        type hint;
        file "named.root";
};

zone "somedomain.com" {
        type master;
        file "somedomain.net";
        allow-transfer {
                11.11.11.11;
                22.22.22.22;
                common-allow-transfer;
        };
};

zone "otherdomain.com" {
        type master;
        file "otherdomain.com";
        allow-transfer {
                33.33.33.33;
                44.44.44.44;
                55.55.55.55;
                common-allow-transfer;
        };
};

And here's an example of what should appear in the edited file:

zone "." { type hint; file "named.root"; };
zone "somedomain.com" { type master; file "somedomain.net"; allow-transfer { 11.11.11.11; 22.22.22.22; common-allow-transfer; }; };
zone "otherdomain.com" { type master; file "otherdomain.com"; allow-transfer { 33.33.33.33; 44.44.44.44; 55.55.55.55; common-allow-transfer; }; };

My CIO and I unsuccessfully searched for existing scripts that convert named.conf into one-line-per-zone format. Using tr and sed, I've managed to 1) turn all tabs into spaces and 2) compress multiple contiguous spaces into a single space. The result is closer to what I need, but I'm still having trouble deleting unwanted newlines while keeping desired newlines. Here's example output which is close to being correct:

zone "." {
 type hint;
 file "named.root"; 
};
zone "somedomain.com" {
 type master;
 file "somedomain.net";
 allow-transfer {
 11.11.11.11;
 22.22.22.22;
 common-allow-transfer;
 };
};
zone "otherdomain.com" {
 type master;
 file "otherdomain.com";
 allow-transfer {
 33.33.33.33;
 44.44.44.44;
 55.55.55.55;
 common-allow-transfer;
 };
};

Tested a few suggested sed, awk, and tr expressions to solve the newline problem, but none of the expressions gave the desired output. Any suggestions you have--even a general direction like "experiment with sed and x,y,z"--would be very appreciated. Thanks!

4

Open up the file in Vim (or just vi) and type:

:g/^zone/.,/^}/j

Voila, you're done.


This runs globally, on every line beginning with zone, the command:

.,/^}/j

Which means, from the current line (.) to the next line that starts with a closing brace, join all those lines together.


If you need to script it, use vi's scripted form, ex:

printf '%s\n' 'g/^zone/.,/^}/j' x | ex file.txt
1

Try this:

sed -n '
    /^zone/,/^};/ H          # append current line to hold space in this range
    /^};/ {                  # at the end of the range:
        s/.*//               #   erase the current line
        x                    #   exchange pattern space with hold space
        s/\n//               #   remove first newline (before "zone")
        s/[[:space:]]\+/ /g  #   condense all other whitespace including newlines
        p                    #   and print this zone record
    }
' named.conf 

result

zone "." { type hint; file "named.root"; };
zone "somedomain.com" { type master; file "somedomain.net"; allow-transfer { 11.11.11.11; 22.22.22.22; common-allow-transfer; }; };
zone "otherdomain.com" { type master; file "otherdomain.com"; allow-transfer { 33.33.33.33; 44.44.44.44; 55.55.55.55; common-allow-transfer; }; };
  • Check the sed documentation (the manual, or info sed) for the commands I used. – glenn jackman Aug 22 '18 at 16:35
0

sed -e ':nextline' -e N -e 's/\n\s*\([^z]\)/\1/' -e 'tnextline' named.conf

  • Thank you! This almost got me there. Just have to tweak a little. Your help is very appreciated. – keyop Aug 22 '18 at 21:23
0

You could do it using the paragraph-mode of awk and Perl tools and the range operator , of the sed tool:

sed -e '
    /^zone/,/^$/!d
    H;/^zone/h;/^$/!{$!d;}
    g;s/[[:space:]]\{1,\}/ /g
    s/ $//
' input.file

awk -vRS= '{$1=$1}1' input.file

perl -pl -00e 's/\s+/ /g' input.file

perl -pl -00e 'tr/\t\040\n/ /s' input.file

Output:

zone "." { type hint; file "named.root"; };
zone "somedomain.com" { type master; file "somedomain.net"; allow-transfer { 11.11.11.11; 22.22.22.22; common-allow-transfer; }; };
zone "otherdomain.com" { type master; file "otherdomain.com"; allow-transfer { 33.33.33.33; 44.44.44.44; 55.55.55.55; common-allow-transfer; }; };

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.