Not knowing what an 'RCS' is or does, and if, as I suspect, this is intended to run as a cron job, adding one new user at a time, then if I were tackling this problem I might set out to do it like this.

Pseudo code.

  1. Open the file rw.
  2. Read until I find the line that starts with the domain of interest.
  3. Read on until I found a line that does not contain the domain of interest remembering position where each line started till I find it.
  4. Once I found it, I know where that line started, append the rest of the file onto the end of the string that has it in.
  5. Rewind to the saved position.
  6. Write the new line.
  7. Re-write the rest.
  8. Close and done.

Perl code

my $datafile = '/etc/postfix/virtual'; =pod # This bits a mess? # First you composite the username and domain together my $req_addr = "$username\@$domain"; # Then you use a very iffy regex to break them apart? my ( $name, $domain ) = $req_addr =~ /^([\w.-]+)(@[\w.-]+)$/ ; =cut # so assuming that $name and $domain contain the right information my ($line, $mark, $rest); open FH, "+<$datafile" or die "Open $main::FH failed; $!\n"; #1 $line = <FH> while $line !~ /^$domain$/o; #2 $mark = tell(FH), $line = <FH> while $line =~ /$domain/o; #3 @rest = ($line, <FH>); #4 truncate( FH, $pos ); #5 print FH "$name\@$domain\t$name\n"; #6 print FH "@rest"; #7 close FH or die warn "Error closing $main::FH; $!\n"; #8

Warning! However, if anything should go wrong whilst your processing, your datafile could end up corrupted.

A better way of doing this would be to use the -spi switches from perlman:perlrun

Something like this

#! perl -wspi.bak BEGIN{ die <<USAGE unless defined($domain) & $domain ne '1' && defined($ +name) & $name ne '1'; Usage: $0 -spi -name=fred --domain=some.com path/to/userfile USAGE my ($started, $finished) = (0,0); } next if $finished; # Just print the rest once +we've done the biz $started = /^$domain/o # look for the start of the + right block or next unless $started; # and just print till we f +ind it $finished = !/$domain/o # Continue just printing ti +ll we find the end or next unless $finished; print "$name\@$domain\t$name\n"; # Then print the new bit END{ unlink $main::ARGV . $^I or warn "Failed to delete backup $main::ARGV$^I; $!\n" }

Which works quite nicely on my system using your sample file format.

The caveat with this (and the preceding and yours) is that if the same user registers several times--as users are apt to do if they don't see immediate results--you will end up with multiple lines for that user.

Fixing this limitation is left AAEFTP.


Well It's better than the Abottoire, but Yorkshire!

In reply to Re: There has got to be a Cleaner Way! by BrowserUk
in thread There has got to be a Cleaner Way! by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.