Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

I know it's wrong but why is it working (sort of)

Status
Not open for further replies.

pinball2k

MIS
Jul 26, 2009
4
US
I've been working on some code to rename MP3 tags. I wrote the following to test out some functions. I wanted to sort out files that began with numbers. I now know about the != and the "ne" (string based) but wonder why this is working.

# PRINTS SECOND LINE IF FILE NAME BEGINS WITH A NUMBER

SAMPLE CODE

#------------------------------
use File::Find;
{
# the base directory where the files are change to a local directory

my $baseDir = "//users//yourName//desktop//MP3s";

my $fileName; # the complete filename with directory prepended
my @fileList; # array to hold the names of the files in the directoy
my $len; # used for array bounds
my $i = -1; #loop counter
find(\&listItNow, $baseDir);


sub listItNow{
print "this is the name-->$_\n";
if ($_ != "-d") { # THIS IS THE BAD PART
### THIS BRANCH TAKEN WITH ANY FILE NAME THAT
###
### STARTS WITH A NUMBER
$i += 1;
$fileList[$i] = $_;
print "BRANCH-$fileList[$i] $i\n";
}
return}

}

#----------------------
#----------------------

What happens is any file that begins with a number, takes the branch. All others do not.
 
This line is wrong:

Code:
if ($_ != "-d") {  # THIS IS THE BAD PART

What it appears to be trying to do is test if the current file is a not a directory, in which case its not a comparison at all, but a simple negation:

Code:
 if (! -d $_) {

But if you really want to see if a filename starts with a number you would use a regexp (among other ways):

Code:
 if ($_ =~ /^\d/) {



------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Well, it does not seem to matter what I have in the quote on the BAD PART line. The same results appear.
 
Hi

Applying Kevin's suggestion is a must, because your original syntax is wrong.

Beside that, I would say you have to check [tt]$_[0][/tt] instead of [tt]$_[/tt]. ( I am not sure, because CPAN is down and I not have that module. But I would give it a try. )

Feherke.
 
Lets look at the code:

Code:
@files  = qw(1foo 2bar poopoo paapaa 4baz);
for (@files) {
   if ($_ != "-d") {
      print "$_\n";
   }
}

The above prints:

1foo
2bar
4baz

which at first glance almost looks correct, but if you remove -d it will still print the same results. This is not really a good thing because it appears the code is actually working when its not. If you add the warnings pragma and retry the code you will get a bunch of warnings.

Code:
use warnings;
@files  = qw(1foo 2bar poopoo paapaa 4baz);
for (@files) {
   if ($_ != "-d") {
      print "$_\n";
   }
}

They will be similar to this:

Argument "1foo" isn't numeric in numeric ne (!=) at script at line 4

So something is happening but not what you think and it does make it sort of look like its working. Now if you really wanted to see if a string starts with a number use the regexp I posted:

Code:
use warnings;
@files  = qw(1foo 2bar poopoo paapaa 4baz);
for (@files) {
   if ($_ =~ /^\d/) {
      print "$_\n";
   }
}

Which prints the same thing as before:

1foo
2bar
4baz


but there are no warnings and its printing the lines that match for the correct reason and not just because perl is trying to figure out what you mean (DWIM: Do What I mean) and since there are no syntax errors in your code it runs and returns results, and they almost look correct, but they are not.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
I understand how to do it correctly, what I don't understand is why it works the way it is. It's just a mental challenge to understand what PERL is really doing.
 
Perl always tries to run and do something, as long as it can run it will. The problem here is that you are using a numeric comparison operator in the wrong way so perl is confused (so to speak). The warnings pragma is telling you that the thing being compared is not numeric which is altering you to a potential problem. If you need a more technical explanation maybe someone else can explain it.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Kevin,
Thanks so much for the time you put into this. The Warning piece is very good. At least it would have alerted me to the issue.

The way it works is very strange because that's what I was looking for; even though it's wrong syntactically.

Thanks again for your help.

Fred
 
No one's spelled out what's going on yet, so I'll have a go:

!= is a numerical comparison. So when you do
Code:
if ($_ != "-d")
It determines a numerical value for $_ and "-d". "-d" contains no digits, so it's treated as 0. If $_ contains only letters that will be 0 too, so the two will be treated as equal even if they're different strings.

To compare them as strings, you need to do this
Code:
if ($_ ne "-d")
Though, as pointed out above, that's probably not what you really want to do either - Kevin's first answer shows you how to do more plausible operations.

-- Chris Hunt
Webmaster & Tragedian
Extra Connections Ltd
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top