FAQ
I posted a question to this list yesterday from the google groups
interface, asking for help with the following. I have since tried to
post additional details in replies to that message using the google
groups site and none of my posts have shown up on the list so let's try
this again the right way.

I have a datafile with 1 line of data, 30 numbers delimited by tildes.
(Sample code below only uses 4 numbers to save time)

I need to open this file, grab this line of data, split it into
individual numbers, perform some simple math (addition) on each
number, and then put the new values back into the datafile, replacing
the original data that was there.

I neglected to mention in my original post that I need to access these
new values elsewhere in the script to perform additional math functions
with them.

I've tried several variations of the code below, including using arrays,
and none of them got through without the script failing. The new
datafile gets written, but it merely contains a ~. The errors I get are
"use of uninitialized values in such and such line" and "variables needs
explicit package name". When the script does run, the variables lose
their values as soon as I close the file after inhaling it, making all
the rest of the actions in the subroutine futile.

the datafile used below initially contains 30 values that were written
previously, and this has been verified over and over.

sub newValues {
my($file) = shift;

open(FILE, "<$file") or die("Unable to open data file.");
while (<FILE>) {
my($a,$b,$c,$d) = split(/~/, $_);
$a = $a+$previousarray[4]; # I've tried to perform this math action
after close(FILE) and get the same result -> failure.
$b = $b+$previousarray[7];
$c = $c+$previousarray[0];
}
close(FILE);
open(FILE, ">$file") || die ("unable to open file");
print FILE ("$a~$b~$c \n");
close(FILE);
}
#end sub

Now my datafile just contains a single tilde and no values. I've also
tried to bring the original data from the datafile into my(@array) and
get the same errors.

Keep in mind I need other subroutines to be able use these new values,
but these local variables lose their values once the file is closed.
I've also tried to declare them as global variables but I'm not doing
something right because the script won't execute.

I really need some help figuring this out if somebody would be kind
enough to help a novice.

Search Discussions

  • Rob Dixon at Feb 5, 2010 at 11:14 am

    Chris Coggins wrote:
    I posted a question to this list yesterday from the google groups
    interface, asking for help with the following. I have since tried to
    post additional details in replies to that message using the google
    groups site and none of my posts have shown up on the list so let's try
    this again the right way.

    I have a datafile with 1 line of data, 30 numbers delimited by tildes.
    (Sample code below only uses 4 numbers to save time)

    I need to open this file, grab this line of data, split it into
    individual numbers, perform some simple math (addition) on each
    number, and then put the new values back into the datafile, replacing
    the original data that was there.

    I neglected to mention in my original post that I need to access these
    new values elsewhere in the script to perform additional math functions
    with them.

    I've tried several variations of the code below, including using arrays,
    and none of them got through without the script failing. The new
    datafile gets written, but it merely contains a ~. The errors I get are
    "use of uninitialized values in such and such line" and "variables needs
    explicit package name". When the script does run, the variables lose
    their values as soon as I close the file after inhaling it, making all
    the rest of the actions in the subroutine futile.

    the datafile used below initially contains 30 values that were written
    previously, and this has been verified over and over.

    sub newValues {
    my($file) = shift;

    open(FILE, "<$file") or die("Unable to open data file.");
    while (<FILE>) {
    my($a,$b,$c,$d) = split(/~/, $_);
    $a = $a+$previousarray[4]; # I've tried to perform this math action
    after close(FILE) and get the same result -> failure.
    $b = $b+$previousarray[7];
    $c = $c+$previousarray[0];
    }
    close(FILE);
    open(FILE, ">$file") || die ("unable to open file");
    print FILE ("$a~$b~$c \n");
    close(FILE);
    }
    #end sub

    Now my datafile just contains a single tilde and no values. I've also
    tried to bring the original data from the datafile into my(@array) and
    get the same errors.

    Keep in mind I need other subroutines to be able use these new values,
    but these local variables lose their values once the file is closed.
    I've also tried to declare them as global variables but I'm not doing
    something right because the script won't execute.

    I really need some help figuring this out if somebody would be kind
    enough to help a novice.
    Hello Chris

    Your lexical variables $a, $b, $c are local to the 'while' block, and do
    not exist outside it. Error "Global symbol xx requires explicit package
    name" is because the variable is not declared. Error "Use of
    uninitialized value..." is because Perl uses a value of 'undef' where
    variables are missing.

    As an aside it is bad form to use meaningless variable names, and $a and
    $b are special names that are used by core Perl so should be avoided.
    Also it is prefereable to use lexical file handles and the
    three-argument form of 'open', and incorporating the standard variable
    $! into the die string will give valuable information about why the
    operation failed.

    Declaring your variables outside the 'while' loop would fix your
    problem, but as you are interested only in the first line of the file it
    is as well to remove the loop altogether. Take a look at the code below
    and see if it meets your requirements.

    HTH,

    Rob


    sub newValues {

    my $file = shift;

    open my $data, '<', $file or die "Unable to open data file: $!";
    my $line = <$data>;
    close $data;

    my @data = split /~/, $line;
    die "Invalid data format" if @data < 3;
    $data[0] += $previousarray[4];
    $data[1] += $previousarray[7];
    $data[2] += $previousarray[0];

    open my $out, '>', $file or die "Unable to open output file: $!";
    print $out join('~', @data[0,1,2]), "\n";
    close $out or die "Failed to close output file: $!";
    }
  • Chris Coggins at Feb 6, 2010 at 10:31 am

    Rob Dixon wrote:
    Chris Coggins wrote:
    I posted a question to this list yesterday from the google groups
    interface, asking for help with the following. I have since tried to
    post additional details in replies to that message using the google
    groups site and none of my posts have shown up on the list so let's
    try this again the right way.

    I have a datafile with 1 line of data, 30 numbers delimited by
    tildes. (Sample code below only uses 4 numbers to save time)

    I need to open this file, grab this line of data, split it into
    individual numbers, perform some simple math (addition) on each
    number, and then put the new values back into the datafile, replacing
    the original data that was there.

    I neglected to mention in my original post that I need to access
    these new values elsewhere in the script to perform additional math
    functions with them.

    I've tried several variations of the code below, including using
    arrays, and none of them got through without the script failing. The
    new datafile gets written, but it merely contains a ~. The errors I
    get are "use of uninitialized values in such and such line" and
    "variables needs explicit package name". When the script does run,
    the variables lose their values as soon as I close the file after
    inhaling it, making all the rest of the actions in the subroutine
    futile.

    the datafile used below initially contains 30 values that were
    written previously, and this has been verified over and over.

    sub newValues {
    my($file) = shift;

    open(FILE, "<$file") or die("Unable to open data file.");
    while (<FILE>) {
    my($a,$b,$c,$d) = split(/~/, $_);
    $a = $a+$previousarray[4]; # I've tried to perform this math action
    after close(FILE) and get the same result -> failure.
    $b = $b+$previousarray[7];
    $c = $c+$previousarray[0];
    }
    close(FILE);
    open(FILE, ">$file") || die ("unable to open file");
    print FILE ("$a~$b~$c \n");
    close(FILE);
    }
    #end sub

    Now my datafile just contains a single tilde and no values. I've also
    tried to bring the original data from the datafile into my(@array)
    and get the same errors.

    Keep in mind I need other subroutines to be able use these new
    values, but these local variables lose their values once the file is
    closed. I've also tried to declare them as global variables but I'm
    not doing something right because the script won't execute.

    I really need some help figuring this out if somebody would be kind
    enough to help a novice.
    Hello Chris

    Your lexical variables $a, $b, $c are local to the 'while' block, and
    do not exist outside it. Error "Global symbol xx requires explicit
    package name" is because the variable is not declared. Error "Use of
    uninitialized value..." is because Perl uses a value of 'undef' where
    variables are missing.

    As an aside it is bad form to use meaningless variable names, and $a
    and $b are special names that are used by core Perl so should be
    avoided. Also it is prefereable to use lexical file handles and the
    three-argument form of 'open', and incorporating the standard variable
    $! into the die string will give valuable information about why the
    operation failed.

    Declaring your variables outside the 'while' loop would fix your
    problem, but as you are interested only in the first line of the file
    it is as well to remove the loop altogether. Take a look at the code
    below and see if it meets your requirements.

    HTH,

    Rob


    sub newValues {

    my $file = shift;

    open my $data, '<', $file or die "Unable to open data file: $!";
    my $line = <$data>;
    close $data;

    my @data = split /~/, $line;
    die "Invalid data format" if @data < 3;
    $data[0] += $previousarray[4];
    $data[1] += $previousarray[7];
    $data[2] += $previousarray[0];

    open my $out, '>', $file or die "Unable to open output file: $!";
    print $out join('~', @data[0,1,2]), "\n";
    close $out or die "Failed to close output file: $!";
    }
    Rob, thank you very much. This worked perfectly, unless my datafile is
    empty at the start. Easiest fix was inserting 30 zero-tildes into the file.

    I have a couple other snags if yall are willing to tolerate the questions.

    1. another script uses data passed into it from an html form. Some of
    the fields are empty, and my "print report file" subroutine prints the
    empty variables because I don't know how to filter them out, and they
    need to be removed from the report. Can someone give me the perfectly
    formed "if" statement that lets me skip over the one or two empty
    variables during the print action? The data being printed to the file is
    stored in an array. See code below.

    print FILE ("Report summary: $taskarray[0] \n"); #this value is good
    print FILE ("Data for task 3: $taskarray[3] \n"); #this value is good
    print FILE ("Data for task 7: $taskarray[7] \n"); #this value is empty,
    don't print this data
    print FILE ("Data for task 2: $taskarray[2] \n"); #this value is empty,
    don't print this data
    print FILE ("Data for task 11: $taskarray[11] \n"); #this value is good
    but needs to be modified, see #2 below

    2. Some of the data being printed above needs to be stripped of some of
    its characters in the string. For example, one of the values is a part
    number with 27 characters. I only need the last 10 characters of the
    string for this report because somebody else is going to fill in the
    front 17 characters with a new part code that I have nothing to do
    with. The string currently looks like this:
    TNA-140ZQ00-170011234567.890. I need it to print to FILE like this:
    ___-_______-______1234567.890, and I need to do this in the same block
    of code above.

    Chris
  • 7 at Feb 6, 2010 at 11:44 am

    On 2/6/10, Chris Coggins wrote:
    Rob Dixon wrote:
    Chris Coggins wrote:
    I posted a question to this list yesterday from the google groups
    interface, asking for help with the following. I have since tried to
    post additional details in replies to that message using the google
    groups site and none of my posts have shown up on the list so let's
    try this again the right way.

    I have a datafile with 1 line of data, 30 numbers delimited by
    tildes. (Sample code below only uses 4 numbers to save time)

    I need to open this file, grab this line of data, split it into
    individual numbers, perform some simple math (addition) on each
    number, and then put the new values back into the datafile, replacing
    the original data that was there.

    I neglected to mention in my original post that I need to access
    these new values elsewhere in the script to perform additional math
    functions with them.

    I've tried several variations of the code below, including using
    arrays, and none of them got through without the script failing. The
    new datafile gets written, but it merely contains a ~. The errors I
    get are "use of uninitialized values in such and such line" and
    "variables needs explicit package name". When the script does run,
    the variables lose their values as soon as I close the file after
    inhaling it, making all the rest of the actions in the subroutine
    futile.

    the datafile used below initially contains 30 values that were
    written previously, and this has been verified over and over.

    sub newValues {
    my($file) = shift;

    open(FILE, "<$file") or die("Unable to open data file.");
    while (<FILE>) {
    my($a,$b,$c,$d) = split(/~/, $_);
    $a = $a+$previousarray[4]; # I've tried to perform this math action
    after close(FILE) and get the same result -> failure.
    $b = $b+$previousarray[7];
    $c = $c+$previousarray[0];
    }
    close(FILE);
    open(FILE, ">$file") || die ("unable to open file");
    print FILE ("$a~$b~$c \n");
    close(FILE);
    }
    #end sub

    Now my datafile just contains a single tilde and no values. I've also
    tried to bring the original data from the datafile into my(@array)
    and get the same errors.

    Keep in mind I need other subroutines to be able use these new
    values, but these local variables lose their values once the file is
    closed. I've also tried to declare them as global variables but I'm
    not doing something right because the script won't execute.

    I really need some help figuring this out if somebody would be kind
    enough to help a novice.
    Hello Chris

    Your lexical variables $a, $b, $c are local to the 'while' block, and
    do not exist outside it. Error "Global symbol xx requires explicit
    package name" is because the variable is not declared. Error "Use of
    uninitialized value..." is because Perl uses a value of 'undef' where
    variables are missing.

    As an aside it is bad form to use meaningless variable names, and $a
    and $b are special names that are used by core Perl so should be
    avoided. Also it is prefereable to use lexical file handles and the
    three-argument form of 'open', and incorporating the standard variable
    $! into the die string will give valuable information about why the
    operation failed.

    Declaring your variables outside the 'while' loop would fix your
    problem, but as you are interested only in the first line of the file
    it is as well to remove the loop altogether. Take a look at the code
    below and see if it meets your requirements.

    HTH,

    Rob


    sub newValues {

    my $file = shift;

    open my $data, '<', $file or die "Unable to open data file: $!";
    my $line = <$data>;
    close $data;

    my @data = split /~/, $line;
    die "Invalid data format" if @data < 3;
    $data[0] += $previousarray[4];
    $data[1] += $previousarray[7];
    $data[2] += $previousarray[0];

    open my $out, '>', $file or die "Unable to open output file: $!";
    print $out join('~', @data[0,1,2]), "\n";
    close $out or die "Failed to close output file: $!";
    }
    Rob, thank you very much. This worked perfectly, unless my datafile is
    empty at the start. Easiest fix was inserting 30 zero-tildes into the file.

    I have a couple other snags if yall are willing to tolerate the questions.

    1. another script uses data passed into it from an html form. Some of
    the fields are empty, and my "print report file" subroutine prints the
    empty variables because I don't know how to filter them out, and they
    need to be removed from the report. Can someone give me the perfectly
    formed "if" statement that lets me skip over the one or two empty
    variables during the print action? The data being printed to the file is
    stored in an array. See code below.

    print FILE ("Report summary: $taskarray[0] \n"); #this value is good
    print FILE ("Data for task 3: $taskarray[3] \n"); #this value is good
    print FILE ("Data for task 7: $taskarray[7] \n"); #this value is empty,
    don't print this data
    print FILE ("Data for task 2: $taskarray[2] \n"); #this value is empty,
    don't print this data
    print FILE ("Data for task 11: $taskarray[11] \n"); #this value is good
    but needs to be modified, see #2 below

    2. Some of the data being printed above needs to be stripped of some of
    its characters in the string. For example, one of the values is a part
    number with 27 characters. I only need the last 10 characters of the
    string for this report because somebody else is going to fill in the
    front 17 characters with a new part code that I have nothing to do
    with. The string currently looks like this:
    TNA-140ZQ00-170011234567.890. I need it to print to FILE like this:
    ___-_______-______1234567.890, and I need to do this in the same block
    of code above.

    Chris

    1) You would have to be more specific as to what an 'empty variable'
    is. Zero? A blank string? undef?


    2)

    use strict;
    use warnings;
    use 5.010;

    my $string = 'TNA-140ZQ00-170011234567.890';
    my $prefix = '___-_______-______';

    my $last_eleven = substr $string, -11;
    say "$prefix$last_eleven";

    --output:--
    ___-_______-______1234567.890


    By the way, you should know that a period is a character. You are
    pretty sloppy in describing your problems. Consider providing *no*
    verbal explanation of your problems. Rather try posting, "I have xxxx
    and I am trying to get yyyy". Here is an example program
    demonstrating what I am trying to do. My *expected* output (or
    error) is this. My *actual* output is this."

    Also, when you have a problem in your actual program, to try and solve
    it you should create another practice program. Try to mimic the
    problem with a 10 line example program, and then post your example
    program--not your real program.
  • Jim Gibson at Feb 6, 2010 at 9:03 pm

    At 5:48 AM -0500 2/6/10, Chris Coggins wrote:
    1. another script uses data passed into it from an html form. Some
    of the fields are empty, and my "print report file" subroutine
    prints the empty variables because I don't know how to filter them
    out, and they need to be removed from the report. Can someone give
    me the perfectly formed "if" statement that lets me skip over the
    one or two empty variables during the print action? The data being
    printed to the file is stored in an array. See code below.

    print FILE ("Report summary: $taskarray[0] \n"); #this value is good
    print FILE ("Data for task 3: $taskarray[3] \n"); #this value is good
    print FILE ("Data for task 7: $taskarray[7] \n"); #this value is
    empty, don't print this data
    print FILE ("Data for task 2: $taskarray[2] \n"); #this value is
    empty, don't print this data
    print FILE ("Data for task 11: $taskarray[11] \n"); #this value is
    good but needs to be modified, see #2 below
    If a scalar variable is empty, i.e. is either undef or an empty
    string '', it will have a false value in a logical expression.
    Therefore, you can test the value of the variable and only print it
    if it is true:

    if( $string ) {
    print "$string\n";
    }

    or the shorter equivalent:

    print "$string\n" if $string;
  • Shlomi Fish at Feb 5, 2010 at 11:16 am
    Hi Chris!
    On Friday 05 Feb 2010 11:56:49 Chris Coggins wrote:
    I posted a question to this list yesterday from the google groups
    interface, asking for help with the following. I have since tried to
    post additional details in replies to that message using the google
    groups site and none of my posts have shown up on the list so let's try
    this again the right way.

    I have a datafile with 1 line of data, 30 numbers delimited by tildes.
    (Sample code below only uses 4 numbers to save time)

    I need to open this file, grab this line of data, split it into
    individual numbers, perform some simple math (addition) on each
    number, and then put the new values back into the datafile, replacing
    the original data that was there.

    I neglected to mention in my original post that I need to access these
    new values elsewhere in the script to perform additional math functions
    with them.

    I've tried several variations of the code below, including using arrays,
    and none of them got through without the script failing. The new
    datafile gets written, but it merely contains a ~. The errors I get are
    "use of uninitialized values in such and such line" and "variables needs
    explicit package name". When the script does run, the variables lose
    their values as soon as I close the file after inhaling it, making all
    the rest of the actions in the subroutine futile.

    the datafile used below initially contains 30 values that were written
    previously, and this has been verified over and over.
    Commenting on your code. Also, did you try using the Perl debugger ("perl -d")
    to debug the code?
    sub newValues {
    my($file) = shift;
    1. Your code needs indentation.

    2. Either do:

    <<
    my $file = shift;
    >>

    Or:

    <<
    my ($file) = @_;
    >>

    Otherwise, it is confusing and the meaning may be lost.

    open(FILE, "<$file") or die("Unable to open data file.");
    1. Don't use bareword filehandles - use lexicals.

    2. Use three args open -

    open my $fh, "<", $file or die...;
    while (<FILE>) {
    Better do while (my $line = <FILE>) instead of relying on $_.
    my($a,$b,$c,$d) = split(/~/, $_);
    Don't call your lexical variables $a and $b - they are special built in
    variables. And you probably want an array here.
    $a = $a+$previousarray[4]; # I've tried to perform this math action
    after close(FILE) and get the same result -> failure.
    $b = $b+$previousarray[7];
    $c = $c+$previousarray[0];
    You are updating the values of $a, $b, and $c, but they:

    1. Will disappear after the loop has exited.

    2. Won't be available after the loop's exit.
    }
    close(FILE);
    open(FILE, ">$file") || die ("unable to open file");
    Again, see my remarks about open.
    print FILE ("$a~$b~$c \n");
    Are you using "strict" and "warnings"?

    Regards,

    Shlomi Fish
    close(FILE);
    }
    #end sub

    Now my datafile just contains a single tilde and no values. I've also
    tried to bring the original data from the datafile into my(@array) and
    get the same errors.

    Keep in mind I need other subroutines to be able use these new values,
    but these local variables lose their values once the file is closed.
    I've also tried to declare them as global variables but I'm not doing
    something right because the script won't execute.

    I really need some help figuring this out if somebody would be kind
    enough to help a novice.
    --
    -----------------------------------------------------------------
    Shlomi Fish http://www.shlomifish.org/
    First stop for Perl beginners - http://perl-begin.org/

    Deletionists delete Wikipedia articles that they consider lame.
    Chuck Norris deletes deletionists whom he considers lame.

    Please reply to list if it's a mailing list post - http://shlom.in/reply .

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedFeb 5, '10 at 9:39a
activeFeb 6, '10 at 9:03p
posts6
users5
websiteperl.org

People

Translate

site design / logo © 2023 Grokbase