0

I am trying to learn Perl here and the tutorial suggests the following code snippet after reading some file:

my $team_number = 42;
my $filename = 'input.txt';

open(my $fh, '<', $filename) or die "cannot open '$filename' $!";

my $found;
while(<$fh>) {
  chomp;
  last if($_ eq "Team $team_number");
}
die "cannot find 'Team $team_number'" if(eof $fh);

I don't quite understand why we need chomp, though. chomp removes the new line. So in each loop we remove the new line at the end of the line, but why? The script does throw an error if you remove the chomp, but I don't understand why.

I understand what chomping does, but I didn't get why that was necessary to match since we're already looping through all the lines - why would you then need to remove the new line? It was only after reading Kallol's post that I realised that eq would fail if not chomped, because the actual string that is looped, then, is Team 42\n. So that's why my question is different from other chomp questions: I didn't know why my code wasn't working without chomp and someone pointed me in the right direction.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Bram Vanroy
  • 27,032
  • 24
  • 137
  • 239
  • 5
    I am not the downvoter, but this is an extremely common question; did you look for a duplicate before posting? – tripleee Feb 17 '16 at 09:12
  • Unrelated but this code is pretty badly written as it would say cannot find Team 42 if it was on the last line... – 123 Feb 17 '16 at 09:31
  • @tripleee I did! There are many questions on chomp and Perl and none of the first batch were helpful for me. Or at least I didn't understand from those questions what was going on as they were not the same as my question. – Bram Vanroy Feb 18 '16 at 08:26
  • The [`chomp` documentation](http://perldoc.perl.org/functions/chomp.html) seems to me like an exhaustive answer. In particular; *"It's often used to remove the newline from the end of an input record when you're worried that the final record may be missing its newline."* – tripleee Feb 18 '16 at 08:53
  • @tripleee I understand that, but I didn't get why that was necessary to match since we're already looping through all the lines - why would you then need to remove the new line? It was only after reading Kallol's post that I realised that `eq` would fail if not chomped, because the *actual* string that is looped, then, is *Team 42\n*. So that's why my question is different from other chomp questions: I didn't know why my code wasn't working withouit chomp and someone pointed me in the right direction. – Bram Vanroy Feb 18 '16 at 09:10

3 Answers3

2

It is reasonable that you don't want the new line when you load text and are working with it. The new lines organize text into a file, in memory you have arrays or other data structures. You don't have to chomp it, you generally want to.

Why the code doesn't do what you intended without the chomp has been explained by Kallol and Sobrique: a new-line remains in $_ which thus doesn't match (the string without a new line) so the file is read to the end and eof returns true. See chomp (orperldoc -f chomp). I don't see that the script "throws an error" though, as you say. It doesn't for me, with or without `chomp'; it just never matches.

And there is another error even with chomp, as noted by 123: if the matching string is the last line in the file, by the time the match is found the file has been read so eof returns true and you get a statement that the string was not found. That you could fix by using a flag, for example (which you have right there), in which case you wouldn't be deciding via eof any more.

That would be a very good thing, because what you have now has a little twisted (and rather brittle!) logic -- which is precisely how this last-line-error came about, of course.

Community
  • 1
  • 1
zdim
  • 64,580
  • 5
  • 52
  • 81
  • But why then doesn't the code work without chomping? – Bram Vanroy Feb 17 '16 at 09:15
  • 1
    Because then `$_` contains a linefeed at the end, so the `eq` test fails. – Sobrique Feb 17 '16 at 09:49
  • Out of these answers, this one gets my upvote. Deferring to other answers regarding why the code doesn't work is a bit of a wart here, though. A good answer should stand on its own, and solve the OP's problem completely. – tripleee Feb 18 '16 at 08:49
  • @tripleee Thank you for commenting! Still don't quite understand why it got downvoted (twice!), in fact. Thank you for the suggestion, I will summarize others' findings in my answer then (and leave this here a bit longer). – zdim Feb 18 '16 at 08:56
  • 1
    All of us get downvoted for no good reason every once in a while. Just keep going and you should end up gaining rep from your answers at a steady rate. I still get upvotes on stuff I posted here when I started, several years ago. – tripleee Feb 18 '16 at 08:59
  • Thank you for the elaborate answer, and the summary of others' findings. +1 + accept ;) – Bram Vanroy Feb 22 '16 at 19:52
  • @BramVanroy You are welcome. I found your question reasonable and worthy asking, given a bit specific code you posted. – zdim Feb 22 '16 at 21:48
  • 1
    @BramVanroy Thank you for this comment, following the action, it is very supportive. This Q-A came with a bit of an internal ride for me, as you can imagine, and it is educational to see how it all played out. Big thanks go to tripleee for responding and for his comments. (I'll remove this in a couple of days.) – zdim Feb 23 '16 at 04:17
2

You would just need to change the match to include a new line if you don't chomp.

while(<$fh>) {
  last if($_ eq "Team $team_number\n");
}
Essex Boy
  • 7,565
  • 2
  • 21
  • 24
0

Chomp removes new line character from the end of the line as you are looping through each line of the file. Since you are matching the line with a text without new line, there is no match found and the file is read until the end. So the last condition to check End-Of-File is true and the "die" statement is executed.

Kallol
  • 302
  • 4
  • 16