in reply to Multiply the numbers in a text file

What does the file look like with the numbers? Is it in a list type format? If so you could load the file into an array and assign the array elements to a variable.

Lets say your number file looks like this
123 12 52 15 27 336

Load the file into an array like so

open FILE, "<", "file.txt"; chomp(@array=<FILE>); close FILE;

This will give you an array which would have the all the values loaded from the file. If you wanted to multiply them by a constant I would loop through the array and do a conditional check on each element. Here is an example script which will write out to a new file

#!/usr/bin/perl my $input = 'input.txt'; my $output = 'output.txt'; my $constant = 15; #number you are multiplying by open FILE, "<", $input; chomp(my @array=<FILE>); close FILE; for(@array) { if ($_ > 20) { open OUTPUT, ">>", $output; print OUTPUT ($_ * $constant)."\n"; close OUTPUT; } }

Replies are listed 'Best First'.
Re^2: Multiply the numbers in a text file
by NetWallah (Canon) on May 09, 2015 at 22:44 UTC
    Adding best practices (Local filehandles, error checking), and efficiency to your code, and adding a zero value check as the OP requested:
    #!/usr/bin/perl use strict; use warnings; my $input = 'input.txt'; my $output = 'output.txt'; my $constant = 15; #number you are multiplying by my $minimum = 20; # Smallest number to multiply my $zero_replace = 666; # Replacement for zero open my $in, "<", $input or die "Could not open $input for reading:$!" +; open my $out, ">>", $output or die "Could not open $output for append: +$!"; while (<$in>){ chomp $_; $_ = $zero_replace if 0 == $_; # next if $_ < $minimum; print $out ($_ * $constant),"\n"; } close $in; close $out;

            "You're only given one little spark of madness. You mustn't lose it."         - Robin Williams

      Your code throws the following error

      Argument "10 0^I" isn't numeric in numeric eq (==) at ./4_Multiply.pl line 16, <$in> line 1.

      Any idea why this is happening

        the first line of your input file is
        10 0<tab>
        and not just a straight number as you were expecting?

        (Or are we supposed to be dealing with more than one number on a line? You don't really say in your original post.)

Re^2: Multiply the numbers in a text file
by Laurent_R (Canon) on May 10, 2015 at 00:01 UTC
    Hello edimusrex,

    Although loading the file into an array can be done and will work with your data sample, it might encounter memory shortage problem if the input data is very large and it is not very efficient. With a problem such as the one in the original post, it is simpler, more efficient and much safer to read the input file line by line and process each line in turn.

    Also the syntax you are proposing (bare word file handles) has been outdated for more than ten years. Look at NetWallah's reply to your post, the syntax in this reply is much more in accordance with the best practices commonly endorsed by the Perl Community these days. Also never open a file without checking if the opening succeeded (or failed).

    I almost considered down voting your post for a few seconds, but I did not because the code seems to be correct (I mean workable), and also because you were obviously trying to be helpful. But you should try to use more modern Perl syntax.

    Je suis Charlie.
      Thanks for the tip. What I've learned in Perl has been taught and learned from some seasoned programmers so it would make sense that I am using "outdated" syntax. I'll take a look at newer standards. I do however always use error checking in production code, just didn't throw it in in my example.
Re^2: Multiply the numbers in a text file
by zegoofer (Initiate) on May 10, 2015 at 00:22 UTC
    Thanks for the reply.

    my file looks something like this

    ncols 498 nrows 541 xllcorner 1394682.720294049475 yllcorner 1751328.700356452260 cellsize 2000.000000000000 NODATA_value -9999 -9999 -9999 -9999 -9999 -9999 -9999 0.09 -0.001

    Though it is a lot bigger in terms of the number of rows and columns. So what i want to do is skip the first six lines and multiply the rest of the text excluding -9999 with a constant. Also all the small negative values should be converted to 0 or -9999. The resulting can be overwritten onto the same text file or onto a new file.

    Thanks a lot for your help

      Now that you've provided some sample data, we can accomplish something. You still need to make your requirements more concrete, though. What qualifies as a "small negative value"? All negative values, or ones below a certain value? If these should be converted to "0 or -9999", which should it choose? If some should be 0 and some should be -9999, based on what criteria? If you hired me to write this script, I would need you to answer those questions.

      To get you started, you can skip the first six lines by simply reading and writing them:

      for (1..6){ $line = <$input_file>; print $output_file $line; }

      Then proceed with your filtering on the remaining lines. I'll guess that you want all negative values smaller than -0.1 replaced with 0 or -9999 alternatively, assume that values are space-delimited, and continue:

      my $M = 5; # constant multiplier my $T = 0.1 # negative number threshold my $al = 0; # alternator while(<$input_file>){ s|([-.\d]+)| if($1 == -9999){ $1; # leave -9999 alone } elsif( $1 < 0 and abs($1) < $T ){ $al++ % 2 ? 0 : -9999; # replace small negative with 0 or -999 +9 } else { $1 * $M; # multiply other numbers by constant } |ge; print $output_file; }

      If you want your changes to replace the original file, the best way to do that is to write to a new file and then copy it over the old file when you're finished. You can do that copy manually, or make that part of your script after you've tested enough to be confident that it will work correctly.

      Aaron B.
      Available for small or large Perl jobs and *nix system administration; see my home node.

        Any value less than zero will be considered as a negative number except -9999, because that represents the no data value.

        Thanks for your help Aaron. I'm trying to get the code running