The previous answers offer alternate solutions, but I think it is also valuable
to review the code that you posted.
Warnings
It is good that you used strict and enabled warnings via -w.
It is generally better to enable lexical warnings via:
use warnings;
instead of globally enabling warnings via -w.
My preference is to use a very strict version of
warnings:
use warnings FATAL => 'all';
In my experience, the warnings have always pointed to a bug in my code.
The issue is that, in some common usage scenarios, it is too easy to miss
the warning messages unless you are looking for them. They can be hard to
spot even if your code generates a small amount of output, not to mention
anything that scrolls off the screen. This option will kill your program
dead so that there is no way to miss the warnings.
Shebang
I have found the following shebang line to be more portable:
#!/usr/bin/env perl
It has served me well for many years across many Unix variants.
Documentation
You should either add a comment near the top of your code to describe
its purpose, or use plain old documentation (POD)
and get manpage-like help with
perldoc.
Input
You have hard-coded the input file path and name inside the code:
my $path = "./input.dat";
This is fine, but the code could be more flexible if you pass it in on the
command line:
my $path = shift;
Naming
This comment is helpful:
# array @grepped of lines containing keyword
However, @grepped is not a very meaningful name for a variable.
It is more common to use plural nouns as names for arrays, such as
@keyword_lines.
There is no need to initialize an array when declaring it:
my @grepped=();
This is cleaner:
my @keyword_lines;
Also, @unique would be better as @unique_lines. This has the added benefit
that is it a different name from your scalar named $unique.
Open
It is better to use
the three-argument form of open
and to use a lexical filehandle, like $fh instead of the bareword FILE.
Also, you almost never want to use double quotes around just a scalar variable like
"$path". The same is true for "$line".
Layout
It is preferable to use 4-space indentation levels; 8 spaces seems like too much.
Also, this line:
if ($line=~ /keyword123/i){push(@grepped,"$line")};
would be better as multiple lines:
if ($line =~ /keyword123/i) {
push @grepped, $line;
}
Note the spacing around operators and braces. I also moved the semicolon inside
the braces.
It is also cleaner to omit parentheses around built-in functions like push.
eq
The following line performs a string compare using eq:
if (scalar @unique eq 1) {
Since you intended to do a numerical compare, it should use ==:
if (@unique == 1) {
There is no need for scalar in this case.