0

Is there any way to use grep to find only elements that exists in specific array? For example :

my @IPS ={"10.20.30","12.13.14","30.40.50"};

my $cmd = `netstat -Aa | grep -c IPS[0] OR IPS[1] OR IPS[2]  `

print "$cmd";

I want cmd to return the number of IPS (only those found in the array) that exists in the output of netstat command. I know I can use " | " or condition but assume that I do not know the number of elements in array.

2 Answers 2

2

Your @IPS array does not contain what you think it contains. I think you probably wanted:

my @IPS = ("10.20.30","12.13.14","30.40.50");

And I'd write that as:

my @IPS = qw(10.20.30 12.13.14 30.40.50);

I know I can use " | " or condition but assume that I do not know the number of elements in array

I don't think that matters at all.

# Need quotemeta() to escape the dots
my $IP_str = join '|', map { quotemeta $_ } @IPS;
my $IP_re  = qr/$IP_str/;

# Keep as much of the processing as possible in Perl-space
my @found = grep { /$IP_str/ } `netstat -Aa`;
say scalar @found;

An alternative to the regex, is to turn @IPS into a hash.

my %IP = map { $_ => 1 } @IPS;
my @found = grep { $IP{$_} } `netstat -Aa`;
say scalar @found;

Update: Actually, that last example doesn't work. You would need to extract the IP addresses from the netstat output before matching against the hash. but I've left it there in case it inspires anyone to expand it.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the detailed answer , I tried the alternative to the regex and the array contains nothing. in this case is it matter how I insert the IPS into IPS array? because I do it by using command : my @IPS = $cmd | tr " " "\n"; chomp @IPS
See my update. That alternative version doesn't work. It doesn't matter how the array is populated - but you need to be sure that the elements contain only the IP addresses. It's very easy, for example, to get newline characters included too - and that won't work.
You need to stop passing so much stuff on to external programs. Perl has its own perfectly useable tr/.../.../ operator :-)
Thanks for the advice , I will try the first solution soon and approve if it works.
0

A quick and dirty way to do this is by utilizing the $" variable in perl:

my @IPS =("10.20.30","12.13.14","30.40.50");
local $"='|';
my $cmd = `netstat -Aa | grep '@IPS' | wc -l`
print "$cmd";

The idea is that $" controls how an array variable is appears when interpolated inside some quotes. So by saying $"='|' we cause the @IPS array to be interpolated as a concatenation of its elements separated by |. Note: you should only use this if you trust of the source of @IPS e.g. if you type it yourself in the code. If it comes from an untrusted external source, the above trick might be dangerous.

Edit: If @IPS does come from an untrusted source, you can validate it first like so

/^[\d.]+$/ or die "Invalid IP address" for @IPS;

3 Comments

Hi redneb , this is a very nice trick I didn't know about. But this is not working for me , I get the value 0 when trying to do this although there are IPS in the output. are you sure about this line " netstat -Aa | grep '@IPS' | wc -l"?
Well , I do not type it myself , I take it from external source and this is why I won't be able to know the number of IPS in the array. any other way you know to do this?
Thanks , I will try this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.