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

Monks
Please help me as I am stumped. I wrote the following code to open up a file, delete lines in the file that start with the words PABPT.ROW and append to the end of the file.
open(SNMPFILE,"+< $local_dir\/cpsnmpagent.cfg"); @ARRAY = <SNMPFILE>; foreach $element (@ARRAY) { if ($element=~/^PABPT.ROW/) { print "$element matches\n"; $element =~ s/$element//; print "element is now $element\n"; } } seek(SNMPFILE,0,0); print SNMPFILE @ARRAY; truncate(SNMPFILE,tell(SNMPFILE)); print SNMPFILE "$conf_chg0\n"; close(SNMPFILE);
The problem is that it finds the lines in question but it only removes the second line found and not the first. What is wrong with my code? Here is the output:
bash-2.03# PABPT.ROW.0= 1000 marks_pabs * 4211 pabd 1 1 5 password matches element is now PABPT.ROW.0= 1000 marks_pabs * 4211 pabd 1 1 5 password PABPT.ROW.0= 34567 pabs_works 10.41.0.70 4211 pabd 1 1 5 password matches element is now
Thanks in advance

Replies are listed 'Best First'.
Re: bewildering array element problem
by gaal (Parson) on Jul 02, 2004 at 09:57 UTC

    Your first line contains the * character. You use the data itself as a regular expression when you try to delete the line, but at that point the asterix is interpreted as a regexp metacharacter. The data does not match /....marks_pabs * 4211..../, because that essentially means ".....marks_pabs, one or more spaces, then 4211". (1)

    Why are you using a regular expression s/// at all to delete the line? You already know exactly what you want to put there, and you want to override the whole $element. So simply assign an empty string.

    From a broader view, though, you shouldn't be slurping the whole file to @ARRAY. That's not scalable. You can read the file line by line and write to a temporary file, eventually copying that over to the original. Or, if you want to edit in-place, check out Tie::File.

    (1) Update: to clarify, an asterix means just *zero* or more times, but / * / means zero or more spaces, then another space.

      Thank you.
      I use this way as the files in question will never be very big. They are only basic config files.
Re: bewildering array element problem
by BrowserUk (Patriarch) on Jul 02, 2004 at 10:26 UTC

    Tie::File just makes this so much easier.

    type junk.dat the quick brown fox jumps over the lazy dog PAPBT.ROW PAPBT.ROW MORE STUFF PAPBT.ROW stuff the quick brown fox jumps over the lazy dog PAPBT.ROW stuff PAPBT.ROW MORE STUFF jumps over the lazy dog jumps over the lazy dog the quick brown fox the quick brown fox jumps over the lazy dog jumps over the lazy dog PAPBT.ROW MORE STUFF PAPBT.ROW perl -mTie::File -e"tie @a,'Tie::File',$ARGV[ 0 ]; @a = grep!/^PAPBT.R +OW/,@a" junk.dat type junk.dat the quick brown fox jumps over the lazy dog the quick brown fox jumps over the lazy dog jumps over the lazy dog jumps over the lazy dog the quick brown fox the quick brown fox jumps over the lazy dog jumps over the lazy dog

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon