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

Hi,

I have a data file in which I need to delete a single entry value. The value will change, but its location in the file will always be the same.

Here is the section of the data file:

4.62399E+09 2.90871E+09 7.17338E+14
sb1 1.0 142r

I want to delete the 7.17338E+14 (or whatever is at that location. In my code I first open this file and find the previous line above sb1 ($oldine and $newline stuff)

#!usr/bin/perl use warnings; use strict; # my ($line)= "4.62399E+09 2.90871E+09 7.17338E+14"; my ($oldline) = "4.62399E+09 2.90871E+09 7.17338E+14"; my ($newline) = "4.62399E+09 2.90871E+09 "; # open (IN, "sdef"); while (<IN>) { if ($_ =~ /sb1 1.0 142r/ ) { $oldline = substr($line, 10, 38); $newline = substr($oldline, 0, 26); } else { $line = $_; } } close(IN); # chomp($oldline); chomp($newline); print "new = $newline\n"; print "old = $oldline\n"; # open (IN, "sdef"); open (OUT, ">sdef_steel") or die "Cannot open file for writing: + $+!" ; while (<IN>) { s/si1 L 1000 1000 /si1 L 1000 /; # works ok s/2150 2151 1035/2150 2151 /; # works ok s/$oldline/$newline/; # doesn't work s/sp1 D (\d+.\d+E[-+]\d+) /sp1 D /; # works ok print OUT $_; } close (IN); close (OUT);

Upon running, I get:

perl test.pl
new = 4.62399E+09 2.90871E+09
old = 4.62399E+09 2.90871E+09 7.17338E+14

Okay, so far so good. But if I grep the new file sdef_steel for 7.17338E+14, it still exists in the sdef_steel file.
It is not recognizing my $oldline string. I think the problem is how I am declaring it.
I have tried both my($oldline) = "txtxxt"; and my($oldline) = "1.234". Of course, the exponential is a combo.
I had thought declaring it as text (string) would be the best method.
So, what is the best way to handle subsitution of exponentials in a single data line?

Replies are listed 'Best First'.
Re: how to read in a line containing exponentials
by suhailck (Friar) on Nov 06, 2010 at 16:12 UTC
    Im not sure i understand your question correctly, but i think changing the line

     s/$oldline/$newline/;                        # doesn't work

    to

     s/\Q$oldline\E/$newline/;

    may help u here.

    See quotemeta
      Thank you!! That worked perfectly.
      Also, Thanks for the link on quotemeta. I will print this out and put it in my notebook.

      Thanks again.

Re: how to read in a line containing exponentials
by kcott (Archbishop) on Nov 06, 2010 at 16:33 UTC

    I did the substitution you're after like this: s{ \s+ \S+ \s* \z }{}msx

    Here's the test code:

    #!perl use 5.12.0; use warnings; my $sought = q{sb1 1.0 142r}; my $last; while (my $line = <DATA>) { chomp $line; if ($line eq $sought) { $last =~ s{ \s+ \S+ \s* \z }{}msx; } say $last if $. > 1; $last = $line; } say $last; __DATA__ pre 2 pre 1 4.62399E+09 2.90871E+09 7.17338E+14 sb1 1.0 142r post 1 post 2

    Here's the output:

    $ match_exp_prob.pl pre 2 pre 1 4.62399E+09 2.90871E+09 sb1 1.0 142r post 1 post 2

    For your code, where I have DATA, you'll want IN and where I have say $last, you'll want print OUT $last, "\n".

    -- Ken

Re: how to read in a line containing exponentials
by ig (Vicar) on Nov 06, 2010 at 17:02 UTC

    It is inefficient to read the input file twice. It doesn't matter if the file is small, but it is easy enough to do everything in a single pass over the file.

    If the data you want to remove is a fixed width at the end of the line, you can use substr - you don't need substitution.

    use strict; use warnings; my $line = <DATA>; while(<DATA>) { if(/^sb1 1.0 142r$/) { print substr($line, 0, -13) . "\n"; } else { print $line; } $line = $_; } print $line; __DATA__ lines before the changed section 4.62399E+09 2.90871E+09 7.17338E+14 sb1 1.0 142r lines after the changed section another instance of the lines to be changed 4.62399E+09 2.90871E+09 7.17338E+14 sb1 1.0 142r another line with 7.17338E+14 in it the rest of the file

    produces

    lines before the changed section 4.62399E+09 2.90871E+09 sb1 1.0 142r lines after the changed section another instance of the lines to be changed 4.62399E+09 2.90871E+09 sb1 1.0 142r another line with 7.17338E+14 in it the rest of the file

    Notice that the output still contains 7.17338E+14. Simple grepping the output file for this value is not a good test for whether the file was changed unless you know the value can't appear elsewhere in the file. I would use diff to see if two text files were different.

    Notice also that the file may be changed in more than one place. This may not be what you want.

    update: if(/^sb1 1.0 142r$/) { is incorrect. There are many alternatives, including if(/^sb1 1\.0 142r$/) { and if($_ eq 'sb1 1.0 142r') {.