Some hints:
- Change the open line to include or die "Could not open $file1: $!";. Alternatively, add use autodie qw( open close ); to the head of your script. This will replace the core open and close functions with wrappers that always check for errors.
- The for loop writing the output should run after the while loop, not inside. You don't want to write intermediate results after each line of input read. You want the total result after having read all input lines.
- The sort expression in the for loop should compare $codes{$a} and $codes{$b}. There is no variable named %name.
- There is no bareword file handle named OUT, so print OUT does not make sense.
- Comparing the result of the print function with results.txt also does not make sense. It seems you want to write to a file named results.txt. For that to work, open a second file handle in write mode, then use print $outputhandle "$name\n";.
- foreach ($line) makes no sense. There is only one line in each round of the while loop.
- The first two lines inside the foreach loop don't make sense. You don't assign anything to $length, and you assign to $name only after having used it. You want to split each line into name and length. See split.
- You wrote two conditions above your code. One is: print the names that ... have a length greater than or equal to 50.. The for loop with the sort will sort and print anything in %codes. If you don't add lines with a length value less than 50 to %codes, they won't appear in the output. next if $length<50; will skip all lines where the lenght is less than 50.
- The other condition is: print the names that appear at least 4 times in the text file. A common trick is to use a hash as the counter. As you aren't really interested in the length at this point, you can use the %codes hash for that. Don't assign anything to $codes{$name}, but increment its value: $codes{$name}++. After the while loop, %codes will contain the counts of every name with a length of at least 50. You only want those with a count of at least 4. Combine sort with grep: for my $name (sort { ... } grep { $codes{$_}>=4 } keys %codes).
- Limit the scope of the variables to the minimum. $name and $length are only required inside the while loop, so declare them there, not outside the loop.
- Close the files you use as soon as you no longer need them. You don't need the input file after having read all lines in the while loop, so close it after the while loop. The output handle is no longer needed after the for loop. Don't forget to check for errors.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)