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

hi , I am new to perl and trying to search for a string in a file and then replace the 2nd field with a updated value
open (OUT, "+>>$file") or die "Can't open $file: $!\n"; while ( <OUT>) { print "$_"; # $test=grep /$key/,$line; if (m/,$key/){ print " found the line $_ \n"; my($key,$val)=split(/,/,$_); $newval=$val+1; $line =~ s/$val/$newval/g; print $line; } }
But I am not getting it right...can anyone help me

Replies are listed 'Best First'.
Re: replace field
by ikegami (Patriarch) on Jul 30, 2009 at 21:03 UTC

    This will update the line as desired:

    s/(,)([^,]+)/ $1 . ($2 + 1) /e

    Update: As others have pointed out, you also have problems regarding trying to change the file in place. I didn't (notice or) address that.

Re: replace field
by jethro (Monsignor) on Jul 30, 2009 at 21:20 UTC

    1) You are using "+>>" which is opening for appending. That means your program is positioned at the end of the file and consequently is finished before it really could start.

    2) Lets say you find the line. You add 1 to it and write the line out again. But that write would necessarily store the new line BEHIND the old line overwriting anything behind it. You could prevent this by remembering where the line started and doing a seek() to that position before writing. But imagine you value was 99. After adding 1 to it there is a character more to fit into the file. Result: The first character on the following line will be overwritten

    So don't try to change a text file by writing into it. Write a new file and rename it to the old name. Check out perlrun and look at the switches -i and -p. Especially -i, it gives a few examples of in-place editing

Re: replace field
by Marshall (Canon) on Jul 30, 2009 at 21:11 UTC
    There is another recent node that talks about updating stuff in the middle of files..
    http://www.perlmonks.org/?node_id=784094
    there is some good info in there and several different approaches to this problem.
Re: replace field
by jwkrahn (Abbot) on Jul 30, 2009 at 21:26 UTC

    Your algorithm won't work because:

    • You are opening the file in append mode which starts out with the file pointer at the end of the file so the while loop has nothing to read.
    • If you didn't use append mode then you have the problem that reads and writes use the same file pointer so you read from one record and then write to the next record leaving the original record untouched.
    • If you fixed that then you still have the problem that $newval=$val+1; may cause the $val field go from one digit to two digits or two digits to three digits etc. causing you to write one byte into the next field.

      I tried to do +> but it seems to empty the file. About $val+1, according to the program logic the digit there will always be single digit, so there is no problem of additional bit. So the only problem now, is to open the file and grep a key and then replace the 2nd field. So anything else I can do now...?

        Maybe you could use Tie::File ? You can process the file as an array and modify the lines in place using ikegami's suggestion.
        HTH!

        Just a something something...
        > means CLOBBER the file (ie delete, recreate)