3

I must be missing something about variable assignment or string comparison. I have a script that's going through a tab-separated file. Unless one particular value in a row is "P", I want to skip to the next line. The code looks like:

1 print "Processing inst_report file...\n";
2 foreach(@inst_report_file){
3    @line=split(/\t/);
4    ($line[13] ne "P") && next;
5    $inst_report{$line[1]}++;
6 }

For some reason, the script would never get to Line 5 even though there were clearly lines with "P" in it.

So debug time!

# Continuing to the breakpoint.
DB<13> c
main::(count.pl:27):        ($line[13] ne "P") && next;

# Proving that this particular array element is indeed "P" with no leading or trailing characters.
DB<13> p "--$line[13]--\n";
--P--

# Proving that I'm not crazy and the Perl string comparison operator really works.
DB<14> p ("P" eq "P");
1

# Now since we've shown that $line[13] eq P, let's run that Boolean again.
DB<15> p ($line[13] eq "P")

# (Blank means FALSE) Whaaaat?

# Let's manually set $line[13]
DB<16> $line[13]="P"

# Now let's try that comparison again...
DB<17> p ($line[13] eq "P")
1
DB<18>

# Now it works.  Why?

I can work around this by prefiltering the input file but bothers me why this doesn't work. Am I missing something obvious?

---loren---

lcheng
  • 31
  • 2
  • 1
    I imagine there's something in your input that we're not seeing and that single "P" you think you have in $line[13] is not really just a single "P". – brian d foy Sep 02 '11 at 00:23
  • 2
    Post a sample of the file you're working with – Zaid Sep 02 '11 at 02:16
  • What version of Perl are you using? What populates `@inst_report_file`? I'd love to see `use Devel::Peek; Dump($line[13]);`. – ikegami Sep 02 '11 at 03:04

4 Answers4

4

Find out what your string really is using:

use Data::Dumper;
local $Data::Dumper::Useqq = 1;
print(Dumper($line[13]));

[ On further review, the guesses below are most likely incorrect. ]

I suspect you have a trailing newline, in which case you want chomp.

You could also have trailing spaces. s/\s+\z// will remove both trailing spaces and a trailing newline.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • `chomp` won't delete a space. – Keith Thompson Sep 02 '11 at 01:57
  • @Keith Thompson, oops! "or space" was edited in, and I didn't consider the whole sentence. Fixed – ikegami Sep 02 '11 at 02:29
  • @TLP, Hum, I seem to have have lept to a false conclusion. Checking using Data::Dumper still good, and if that doesn't help it could be a weird scalar and Devel::Peek might give a clue as to what's wrong. – ikegami Sep 02 '11 at 03:08
1

Have you tried printing out the string characters with ord?

say ord for (split //, $line[13]);

If, for example, you have a \0 in there, it might not show up in a regular print. With the string P\0, I get:

$ perl -wE '$a="P\0"; say "--$a--"; say ord for (split //, $a);'
--P--
80
0
TLP
  • 66,756
  • 10
  • 92
  • 149
1

Unless there are unprintable characters in the input, it's not clear why your code doesn't work. Having said that, I would still write that statement as:

next unless $line[13] eq "P";

or

next unless $line[13] =~ /^P$/; (Theoretically this could be faster.)

You will not need to pre-filter the data.

RET
  • 9,100
  • 1
  • 28
  • 33
0

Are you sure $line[13] isn't supposed to be $line[12]?

Christopher Neylan
  • 8,018
  • 3
  • 38
  • 51