Anirban Adhikary wrote:
Dear List
I have write the The following code to check a file and print only distinct
lines to a new file and skips the duplicate lines. My source file is as
follows
hello how are you?
hello how are you?
What language did you want to use?
What language did you want to use?
I am here
You are there
this is my first perl script
What language did you want to use?
###############################################################################
my code is as follows
#use strict;
#use warnings;
Never comment out these lines - they help enormously to find simple errors.
print "Enter the Absolutepath of the file\t";
my $input=<STDIN>;
chomp($input);
dup($input);
sub dup
{
my $filename=shift;
my $count=0;
my @arr;
my $el;
my $element;
- Variables should be declared as close as possible to their point of first use.
- Try to use meaningful variable names; the @ in @arr means 'array' so you have
something called "array arr". Also the difference between the function of $el
and $element isn't clear from their names.
open(FH,"$filename");
while(<FH>)
- You must always check whether a file open succeeded.
- $filename should stand on its own. Read the perlfaq article
perldoc -q quoting
entitled What's wrong with always quoting "$vars"?
- The three-parameter form of open and lexical file handles are preferred, like this
open my $fh, '<', $filename or die $!;
while (<$fh>) {
{
chomp($_);
$element = $_;
if($count ==0)
{
push(@arr,$element);
$count+=1;
print "Count is $count\n";
$count isn't a count, as it is only incremented when it is zero and never used
thereafter. You also don't need it at all, so you can remove this if statement
altogether.
}
else
{
foreach $el(@arr)
{
my $len=$#arr;
$len is the index of the last element of @arr, not its length. Use
my $len = @arr;
to get that.
chomp($el);
The strings were chomped before they were added to @arr so there is no need to
do it again.
# print "$element\n";
#print "The length of arr is $len\n";
if($el == $element)
The == operator is for comparing numbers; to compare strings you must use
eq. This is why your elsif block wasn't being executed: the values are being
forced to numbers before they are compared, and since non-numeric strings
evaluate as zero they were always numerically equal.
If you had left warnings enabled you would have a message to tell you this.
{
print "\t######Inside If######\t\n";
print $element."\n";
next;
#push(@arr,$_);
}
elsif($el != $element)
There is no need to test again. If
$el eq $element
failed, then
$el ne $element
must succeed, and you need only an 'else' here.
{
push(@arr,$element);
You shouldn't modify an array that you're currently iterating over, as the
results aren't guaranteed and anything may happen. In other words, don't write
foreach (@arr) {
:
push @arr, $val;
:
}
print "\t########Inside Elseif\n";
#next;
}
}
}
- The braces aren't paired properly in your program. I presume an extra one
belongs here.
- You test each new line again /every/ element in @arr, and push the line onto
the array /every time/ it finds an array element that doesn't match. I assume
you want to push the new line onto the array only if none of the elements match?
Something like this perhaps
while (my $element = <$fh>) {
chomp $element;
my $found;
foreach my $el(@arr) {
if ($el eq $element) {
$found++;
last;
}
}
if (not $found) {
print "$element\n";
push @arr,$element;
}
}
}
###############################################################
The problems I am facing are
1) The code is not getting entered into elsif block
2) I am comparing between 2 strings but if I use "eq" or "ne" for
comparison I am getting some horrible output so I am using numeric
comparison.
3)If I am giving print the $element variable outside foreach loop it is
getting printed but Inside foreach loop it is not showing anything.
Can anybody Please suggest me where I am making the mistake?
HTH,
Rob