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

Hi Monks, So I have two .txt files
File 1 Start Stop Name 234 388 abc 458 267 pqr ... ... 873 490 xyz
File 2 Name abc dfr hyt hig wer pqr ... ... xyz
What I have done is read the file 2 names and if they occur in file 1 then get an output for those names with their respective start and stops. For eg: abc and pqr of file 2 occur in file 1 hence,
Output file 234 388 abc 458 267 pqr
What my problem is that the last entry which is 873     490    xyz should appear as the last entry in my output file but it isn't. I get all the others but the last entry isn't showing up on my output file. Any idea as to why this must be happening? Here is my code:
#!/usr/bin/perl # Open info file, and read in all the name start and stops my $input_file = "/Users/myfolder/inputfile.txt"; die "Cannot open $input_file\n" unless (open(IN, $input_file)); my %name_and_Start_Stop; while (chomp($line = <IN>)) { my (@columns) = split /\s+/, $line; my $name = $columns[3]; my $Start = $columns[1]; my $Stop = $columns[2]; $name_and_Start{$name} = $Start; $name_and_Stop{$name} = $Stop; } close(IN); # Open the input file, and read each name die "name_list.txt" unless open(IN, "name_list.txt"); #Open output file and write the name start and stops die "output.txt" unless(open(OUT,"> output.txt")); while (chomp($symbol = <IN>)) { my $Start = $name_and_Start{$name}; my $Stop = $name_and_Stop{$name}; print OUT "$Start\ $Stop \ $name \n"; } close(OUT); close(IN);
Why isn't it outputting the last name xyz? Is it something in the split function?

Replies are listed 'Best First'.
Re: perl leaving out the last value?
by tobyink (Canon) on Apr 17, 2012 at 21:55 UTC

    Here's your problem:

    while (chomp($symbol = <IN>))

    The chomp function returns the number of characters chopped off the end of the line. chomp removes is a line break character. If you have no line break at the end of your text file, then chomp will not remove any characters, thus returns 0. So for the last line, you end up with:

    while (0)

    So the block does not get executed.

    Try replacing constructions like this:

    while (chomp($symbol = <IN>)) {

    with this instead:

    while (defined($symbol = <IN>)) { chomp($symbol);
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      while (defined($symbol = <IN>))

      With this particular construct, Perl automatically adds the defined(), so you can safely omit it if you prefer brevity.

      $ perl -MO=Deparse -e'while ($symbol = <IN>) { chomp($symbol) }' while (defined($symbol = <IN>)) { chomp $symbol; } -e syntax OK
Re: perl leaving out the last value?
by davido (Cardinal) on Apr 17, 2012 at 21:59 UTC

    This line (repeated twice with different identifiers):

    while (chomp($symbol = <IN>))

    ... doesn't do what you want. chomp returns the total number of characters removed. Your last line has no line ending, so no characters are being removed. Since no characters are being removed, the return value of chomp, on the last iteration, is the moral equivelant of 'false'. Thus, the while() loop terminates without processing the last line.

    Move the chomp inside the loop.

    Additional reference on using the diamond operator: <>, truth and falsehood, and while loops. Also perfaq5. Three of those links provide examples of where to place the chomp.

    Update: The documentation for chomp may actually contribute to confusion, since it shows both the correct placement within a while(){} loop, and also an example of how to chomp a single file-read outside of the context of a loop, in a way that would be inappropriate in a while loop.


    Dave

Re: perl leaving out the last value?
by perllearner007 (Acolyte) on Apr 17, 2012 at 22:52 UTC
    Thank you all for your replies! I am revising it..Will update if I still face any issues. Thanks again.