Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re: Appending to a file.

by tobyink (Canon)
on May 07, 2012 at 16:02 UTC ( [id://969288]=note: print w/replies, xml ) Need Help??


in reply to Appending to a file.

Before I say anything else, I'll warn you against that little ($$) thing. That's called a "prototype" and it doesn't do what you think it does. In most situations, prototypes are unhelpful.

Anyway, your problem is that you read each line of the file into memory, do something with it, and then don't write it anywhere. What you want to do is be opening both an input filehandle and an output filehandle, and writing the line to the output filehandle when you're done with it. Something like this:

sub addSecondary { my ($email, $secondary) = @_; open my $input, '<', 'registration.dat'; open my $output, '>', 'registration.tmp'; while (<$input>) { chomp; my $line = $_; if ($line =~ /$email/) { $line =~ s/nodata/$secondary/gi; } print $output "$line\n"; } close $input; close $output; unlink 'registration.dat'; rename 'registration.tmp' 'registration.dat'; }

(Note to pedants: for cross-platform compatibility unlink 'filename' is better written as 1 while unlink 'filename' because some operating systems allows multiple versions of the same file to be stored.)

There are various modules that make line-by-line file editing easier. Corion mentioned Tie::File. I happen to be a fan of File::Slurp. Here's an example using that...

use File::Slurp qw(:edit); sub addSecondary { my ($email, $secondary) = @_; edit_file_lines { s/nodata/$secondary/gi if /$email/ } 'registration.dat'; }
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

Replies are listed 'Best First'.
Re^2: Appending to a file.
by xavierarmadillo (Initiate) on May 07, 2012 at 16:50 UTC
    Wow thank you. I am used to vb and c#, not PERL. It is so different to me. I changed it to
    sub addSecondary() { my ($email, $secondary) = @_; use Tie::File; tie @array, 'Tie::File', 'registration.dat'; for (@array) { s/0;nodata/1;$secondary/gi if /$email/ } untie @array; }
    And it works now. What I don't get is why s/0;nodata/1;$secondary/gi if /$email/ works. There is no semicolon at the end and it is not like any function I have seen. I am used to something = something type notation. How does it even know what to look at and compare?
      for (@array) { s/0;nodata/1;$secondary/gi if /$email/ }

      This would be (essentially) shorthand for:

      for my $_ (@array) # 'my $_' is a little bit of a fudge { $_ =~ s/0;nodata/1;$secondary/gi if $_ =~ /$email/ }

      See perlvar for a little more explanation.

      --MidLifeXis

      There's a global variable (though in recent versions of Perl it can be made more local on request) in Perl called $_. Many Perl functions, operators and looping constructs operate on $_ if you don't give them another variable to operate on instead.

      For example, rather than:

      foreach my $item (@array) { print($item); }

      You can take advantage of the fact that the default name used by foreach is $_, and the default thing printed by print is $_, and instead write:

      for (@array) # note "for" and "foreach" are synonyms { print; }

      Or just:

      print for @array;

      Applying the same logic to your loop, the for is assigning each item in @array to $_; and if /$email/ is shorthand for if $_ =~ /email/; etc.

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

      xavierarmadillo: I see that in your latest posting the substitution
          s/nodata/$secondary/gi
      has become
          s/0;nodata/1;$secondary/gi
      adding '0;' and '1;' to the mix. Maybe this is intentional, but I just thought I'd mention it.

      Another point is that you are now defining the  addSecondary function with an empty prototype, meaning that the function takes no arguments — and then you pass it two arguments! This suggests to me that you are calling the function in a way that causes Perl (not PERL) to ignore prototypes. If prototypes do nothing in your program, or you don't fully understand them, or both, why bother to use them?

      The final and perhaps most important point is that it is wise always to enable warnings and strictures at the beginning of a program, and as you are a newcomer to Perl, to enable diagnostics. So your program would begin with the following lines:
          use warnings;
          use strict;
          use diagnostics;  # for good measure
      See warnings, strict and diagnostics.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (7)
As of 2024-03-19 03:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found