Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

A Better Way

by toniax (Scribe)
on Nov 04, 2010 at 16:11 UTC ( #869497=perlquestion: print w/replies, xml ) Need Help??
toniax has asked for the wisdom of the Perl Monks concerning the following question:

Hello Everyone,
I figured out the solution to my problem . With some help from a tie example below, Ken was so kind to point out, and remembering the way arrays assign [0] [1] [2] and so on.
Well I am sure most of you knew this , But I will post it anyway I can not believe the fix for my original code was so simple , right under my nose.
open(XFIL,"var.txt") || die $!; @main = <XFIL>; close(XFIL); open(XFIL,">var.txt") || die $!; foreach $line (@main) { @main[0] =~ s/some data/this is the first line replaced/; print XFIL $line ; } close(XFIL);
Hello again everyone, Sorry about being so cryptic last time I asked this. I will put my question in code. I created a way to do what I want but it seems so cumbersome. I am sure a better way exist? well here is the code

*Update This code replaces only ONE instance((meaning only one line) (well that is what the final result is)), not all. Hence one reason I created it in this bizarre fashion .
I am also new to programing ,another reason. Thanks again everyone for all your help
open(XFIL,"var.txt") || die $!; @main = <XFIL>; close(XFIL); open(XFIL,">var.txt") || die $!; foreach $line (@main) { $line =~ s/\n/replace/g; print XFIL $line; } close(XFIL); open(XFIL,"var.txt") || die $!; @main = <XFIL>; close(XFIL); open(XFIL,">var.txt") || die $!; foreach $line (@main) { $line =~ s/the line to be replaced/this is the new line/; $line =~ s/replace/\n/g; print XFIL $line; } close(XFIL);

Replies are listed 'Best First'.
Re: A Better Way
by moritz (Cardinal) on Nov 04, 2010 at 16:37 UTC
    No, it doesn't have to be this cumbersome. There's no reason to write an array to a file, and then read the file and fill the array from the file.

    I also don't see why you need to replace each newline with replace, and then later on do the reverse substitution.

    It seems to me your whole script could be replaced by

    $ perl -i -pe 's/the line to be replaced/this is the new line/' var.tx +t
    Perl 6 - links to (nearly) everything that is Perl 6.
      Thanks for your reply . I am new to programing . I did not know you could use a one liner in a cgi program. Would that not have to be called with system()? I am not familiar with one liners. Does that code replace all instances or just the first one is reads ? The reason I created my program in the above way Is so it only replaces the First Line in the Loop not Every Line it Loop Thanks again for all your help
        I did not know you could use a one liner in a cgi program

        And I did not know that you wrote a CGI program. It didn't say so anywhere in your original post, and since your program doesn't write a Content-Type header, it can't be valid CGI either.

        That said, you can still apply the -i option on the shebang line, see perlrun.

        Perl 6 - links to (nearly) everything that is Perl 6.
Re: A Better Way
by kcott (Canon) on Nov 04, 2010 at 17:21 UTC

    Here's a less cumbersome way :-)

    use strict; use warnings; use Tie::File; tie my @xfil, 'Tie::File', 'var.txt' or die $!; @xfil = map { s/the line to be replaced/this is the new line/; $_ } @x +fil; untie @xfil;

    -- Ken

      Hi Ken Thanks for your reply and the info on the mod tie One more question. Does that replace all of the instances or just the first one it gets to ? Thanks again

        It operates on every line. On each line, there will be, at most, one substitution. If you want multiple substitutions on a line, add the 'g' modifier (see perlre for details) like this:

        s/the line to be replaced/this is the new line/g

        -- Ken

Re: A Better Way
by eyepopslikeamosquito (Chancellor) on Nov 04, 2010 at 20:38 UTC

    Be aware that the way you've written the code is unsound in that it offers the potential for permanent (and possibly silent) data loss. Consider what happens if your:

    print XFIL $line;
    fails. You're not checking print's return value, so you may not even be aware that it's failed. If it fails, your var.txt file will be corrupted. If you don't have a backup copy, you will have suffered permanent data loss.

    Apart from the possibility of print failing (due to disk full or disk quota exceeded, for example), suppose your program gets interrupted during the print loop (via CTRL-C or other signal, OS restart, or a power failure, for instance). Because it was interrupted, your program had not finished writing the var.txt file. So when you now re-run your program, you will read (and write) an incomplete var.txt file. And again, you may not be immediately aware that you've (permanently) lost data.

    I assume Tie::File will deal sensibly with these sort of routine robustness and reliability issues. If you don't use Tie::File, you can make your program more robust by:

    1. Write the output file to a new temporary file.
    2. Only after carefully checking that the temporary file has indeed been written without error, rename the temporary file to var.txt. (Note that the rename should be atomic on Unix systems, so there is minimal risk of data loss).

    Update: See also Perl Best Practices book: is this one a best practice or a dodgy practice?.

      Hello eyepop,
      I am aware of that. That is my next item I will be working on.Thanks for the suggestion and the book link.
      This program I am working on seems never ending, but I do not mind. I am starting to get addicted to Perl for some strange reason.
Re: A Better Way
by talexb (Canon) on Nov 04, 2010 at 17:26 UTC

    I can also recommend the excellent Tie::File which ties an array to a file. Make a change in the array, and that change is reflected in the file. Really very cool.

    Alex / talexb / Toronto

    "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://869497]
Approved by talexb
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2017-03-30 02:03 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (353 votes). Check out past polls.