开发者

How to convert this shell script to a platform independent Perl script?

I have a cshell script that is something like this:

`netstat -ap | & grep tcp | grep myprocess | awk '{print $4}' | awk 'BEGIN { FS = :"}{print $2}'`

This is how it works

1.

$ netstat -ap | & grep tcp | grep myprocess
tcp    0    0    *:1234     *:*      LISTEN      8888/myprocess

2.

$ netstat -ap | & grep tcp | grep myprocess | awk '{print $4}'
*:1234

3.

$ netstat -ap | & grep tcp | grep myprocess | awk '{print $4}' | awk 'BEGIN { FS = ":"}{print $2}'`
1234

I need to make this as portable as possible using Perl. I think portability can't be guaranteed without the behaviour of netstat and grep, so I will try to make sure that they are supported on the target systems.

I am looking for

  • Any general consid开发者_C百科erations to keep in mind to make the Perl script portable?
  • How can I replicate the awk behaviour in Perl?
  • Can I also replicate the behavior of grep in Perl? Is that advisable (I'll do it only if Perl's grep has any advantages)?

[I am targeting all prevalent Windows and Linux versions here]


There's a netstat for Windows, but its -p doesn't do what you want.

As for the rest of the functionality, you could use

#! /usr/bin/perl

use warnings;
use strict;

die "Usage: $0 program\n" unless @ARGV == 1;

# e.g., ... 1234/myprocess
my $prog = qr< / \Q$ARGV[0]\E $ >x;  # / fix SO highlighting

no warnings 'exec';
open my $netstat, "-|", "netstat", "-ap"
  or die "$0: cannot start netstat: $!";

while (<$netstat>) {
  my @f = split;
  next unless $f[0] eq "tcp" && $f[-1] =~ /$prog/;

  (my $local = $f[3]) =~ s/^.*://;
  print $local, "\n";
}

For each line of netstat output that's a TCP connection and associated with the program named on the command line, grab the local address (column 4), remove everything through the last colon in the string—which should leave the port—and print the result.


In general, perl can do anything that awk or grep can do, and if cross platform operation is important, keeping all of your logic in one program can help (no reliance on the shell).

Something like this might work for you:

perl -ne 'if (/tcp/ and /myprocess/) { (split /\s+/)[3] =~ /(\d+)/; print $1 }'

Untested, but it should be close. This one-liner expects the netstat input on stdin.

You can also do everything in Perl as follows:

#!/usr/bin/env perl
use warnings;
use strict;

open my $netstat, '-|', 'netstat -ap';

while (<$netstat>) {

    next unless /tcp/ and /myprocess/;

    my @fields = split /\s+/;

    if ($fields[3] =~ /(\d+)/) { print "$1\n" }
}


Seems the most non-portable thing is the netstat call, but:

netstat -ap | perl -lane '
    next unless /tcp/ and /myprocess/;  # this is the "grep" part
    print((split /:/, $F[3])[-1]); # this is the "awk" part
'

or, stick with awk, which can easily do what grep does:

netstat -ap | awk '/tcp/ && /myprocess/ {split($4, a, /:/); print a[2]}'

To pass "myprocess" as a variable into the awk script:

netstat -ap | awk -v proc="myprocess" '/tcp/ && $0 ~ proc {split($4, a, /:/); print a[2]}'


To replicate the awk script behavior in perl, there is a command a2p that should come with most perl distributions.

perl supports pattern matching out of the box, and its undoubtedly more powerful than grep

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜