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

Monks, Lets start with the fact that i am not a perl coder - just a bit of a newbie. I have a variable $domain which contains data in the form of foo.com and i have a file, namely /etc/postfix/virtual which looks like this:
foo.com VIRTUALDOMAIN @foo.com bob user1@foo.com bob user2@foo.com john bar.com VIRTUALDOMAIN @bar.com bob user1@bar.com chris test.com VIRTUALDOMAIN @test.com mike
This file is used by postfix to map e-mail addresses to user accounts, and must be kept in this formatting. Say if i have a new user that is called terry and wants the e-mail address of tag@foo.com then the line 'tag@foo.com terry' must be placed directly below the entry 'user2@foo.com john'. This applies to the other domains too, like billy wants an e-mail address of bill@bar.com, so the script must seek to below 'user1@bar.com chris' and write this data there. Thinking about it now, it would probably be easiest to seek to the '@foo.com bob', do a return and put the data in below that. Thanks People

Replies are listed 'Best First'.
Re: Seeking and Printing
by DamnDirtyApe (Curate) on Aug 14, 2002 at 17:59 UTC

    Here's one way to do it, using Tie::File. A couple of caveats:

    • The regex isn't bulletproof, and will likely fail if you pass it anything unusual. Read perlre and adjust to taste.
    • Since this was just a quick script, it doesn't account for not finding the domain in the file.
    • If anyone knows a more graceful way to add a line to the middle of a file with Tie::File, please let me know.
    #! /usr/bin/perl use strict ; use warnings ; $|++ ; use Tie::File ; my $datafile = 'test_a.dat' ; my $username = 'terry' ; my $req_addr = 'tag@foo.com' ; my ( $name, $domain ) = $req_addr =~ /^([\w.-]+)(@[\w.-]+)$/ ; tie my @virtual, 'Tie::File', $datafile or die $! ; my $row = 0 ; $row++ until $virtual[$row] =~ $domain ; $virtual[$row] .= "\n$req_addr\t$username\n" ; untie @virtual ; __END__

    _______________
    DamnDirtyApe
    Those who know that they are profound strive for clarity. Those who
    would like to seem profound to the crowd strive for obscurity.
                --Friedrich Nietzsche
      is there any way to do it with out the additional modules? there should be no problems with the domain not existing either.

        Yes, though Tie::File isn't really an "additional module," since it's now part of the 5.8.0 distribution. Here's how you could do it w/o Tie::File:

        #! /usr/bin/perl use strict ; use warnings ; $|++ ; my $datafile = 'test_a.dat' ; my $username = 'terry' ; my $req_addr = 'tag@foo.com' ; my ( $name, $domain ) = $req_addr =~ /^([\w.-]+)(@[\w.-]+)$/ ; open FH, $datafile or die "Couldn't read $datafile: $!" ; my @virtual = <FH> ; close FH ; open FH, ">$datafile" or die "Couldn't write $datafile: $!" ; my $wrote_it = 0 ; for ( @virtual ) { print FH $_ ; if ( $_ =~ /$domain/ && !$wrote_it ) { print FH "$req_addr\t$username\n" ; $wrote_it++ ; } } close FH ; __END__

        _______________
        DamnDirtyApe
        Those who know that they are profound strive for clarity. Those who
        would like to seem profound to the crowd strive for obscurity.
                    --Friedrich Nietzsche
Re: Seeking and Printing
by Anonymous Monk on Aug 14, 2002 at 17:29 UTC
    so basicaly, if the variable $domain contains bar.com the script needs to seek to the end of the line '@bar.com bob', do a return and then do a print there