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

Hi everyone,

I'm trying to update the phone numbers in a ASCII file but for some reason it's not working.

Here is a portion of the file(personel.txt):

#id|Name|family|phone
0001|Tony|Hintz|0407561232
0002|James|Green|0403652154
0003|Isaac|Thomas|0403655871

I'm greping a line basing on the id and then changing the phone number and then trying to replace it back into the file, but for some reason it is not working. Have a look on my code:

#!/usr/bin/perl -w $newdigit="+615"; $id="0001"; $line = `grep $id personel.txt`; ($id, $name, $family, $oldphone)=split(/\|/, $line); $newphone = $newdigit .$oldphone; $NewLine= join ("|",$id, $name, $family, $newphone); open(PERS,">>personel.txt"); while (<PERS>) { s/$line/$NewLine/; }


can anyone tell me what's going wrong? and if there any better way to do it?

TANX,
a very newbie

Ps: $NewLine reflects the changes but i'm not able to write it back to the file.

20030606 Edit by Corion: Changed title from "Substitue!"

Replies are listed 'Best First'.
Re: Substitue!
by davorg (Chancellor) on Jun 06, 2003 at 08:02 UTC

    There's really no need for a program here. You can do it all from the command line.

    $ perl -i.bak -pe 's/(\d+)$/+615$1/ if /^0001/' your_filename
    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      Indeed. All you need is the -i option, and possibly the -p option (see perlrun) to do the loop and the printing. You can even use them in regular scripts. Note that with the -p option, anything you want to do before the loop needs to be in a BEGIN block.

      In the next code, the -l option takes care of the newlines.

      #!/usr/bin/perl -p -i.bak -l BEGIN { @ARGV = 'personel.txt'; $newdigit="+615"; $id="0001"; } if(/^$id\|/o) { my($id, $name, $family, $oldphone) = split /\|/; $newphone = $newdigit .$oldphone; $_ = join ("|", $id, $name, $family, $newphone); }

      p.s. You're trying to read from a file opened for append. Jeez.

        Bart, tanx for ur reply. Your code is working perfectly, however if i try to call it from a web browser through a get method (passing the id) it won't work!.. any clue why this is happening..
Re: Substitue!
by Corion (Patriarch) on Jun 06, 2003 at 08:00 UTC

    As you have noted, this does not change the file in place. You have two possible approaches here :

    1. Create a second file instead of personel.txt, and overwrite personel.txt at the end of your program
    2. Use the Tie::File module to treat your file as an array
    The first approach will need almost no modification of your script and only the addition of the rename code to the end of your script. The second approach will need some modification of your script, but after that, your script will also run on a system that does not have grep installed. An example for how the second approach could look is :

    #!/usr/bin/perl -w use strict; use Tie::File; my $newdigit="+615"; my $search_id="0001"; my $personel_filename; my @personel; tie @personel, 'Tie::File', File::Spec->catfile($FindBin::Bin,$persone +l_filename) or die "Couldn't read '$personel_filename'\n"; for my $line (@personel) { my ($id, $name, $family, $oldphone)=split(/\|/, $line); # Look if we want to replace the phone if ($id eq $search_id) { $newphone = $newdigit .$oldphone; # And overwrite the line in the array $line = join ("|",$id, $name, $family, $newphone); }; };
Re: Substitue!
by arthas (Hermit) on Jun 06, 2003 at 08:04 UTC

    You can't do that that way. You need to read the whole file, substitute what you need, and rewrithe the whole file.

    Alternatively, you can achieve your target by using this, directly from the command line:

    perl -pi -e's/\|(\d+)$/|+615$1/ if /^0001/' personel.txt

    You need to specify the ID of the person you need to change instead of 0001.

    Hope this helps!

    Michele.

    Update: I forgot to include the condition, now I fixed.

      That would change EVERY phone number not just one.

      Update: Okay ;-)

Re: Substitution of text within a file
by linux454 (Pilgrim) on Jun 06, 2003 at 14:03 UTC
    While Corion gave you the better way (Tie::File),
    the reason that what you have written isn't working is
    that you opened the file as write-only. This means that
    The while(<PERS>) loop did nothing. In fact it didn't
    even go through the loop. To do what you were wanting to
    do you need to use the "+<" open operator instead of ">>"
    Note: Don't use "+>" unless you want to truncate the file first
Re: Substitution of text within a file
by aquarium (Curate) on Jun 06, 2003 at 14:32 UTC
    does it have to be done in perl? you can do it with one substitution command in sed/vi/ex. you can even save this tiny command script and apply it again whenever you get such a file to mangle again.
    in vi:
    %s/\|\([0-9]\)/|+615\1/
      Tanx for ur replies.

      The point is that I can't use a command line to do it as the file contains another decimal fields, plus i've to run a test on the phone number before i add +615.

      I Just gave a simple file as an example.