如何将此shell脚本转换为独立于平台的Perl脚本?

时间:2010-08-24 20:37:18

标签: perl shell awk grep portability

我有一个类似的cshell脚本:

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

这就是它的工作原理

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

我需要使用Perl使其尽可能便携。我认为如果没有netstatgrep的行为,就无法保证可移植性,因此我将尝试确保它们在目标系统上受支持。

我正在寻找

  • 要记住使Perl脚本可移植的一般注意事项吗?
  • 如何在Perl中复制awk行为?
  • 我是否还可以在Perl中复制grep的行为?这是可取的(我只会在Perl的grep有任何优势时才这样做)?

[我的目标是所有流行的Windows和Linux版本]

4 个答案:

答案 0 :(得分:1)

有一个netstat for Windows,但其-p没有达到你想要的效果。

至于其余功能,您可以使用

#! /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";
}

对于netstat输出的每一行,它是一个TCP连接并与命令行上命名的程序相关联,获取本地地址(第4列),通过字符串中的最后一个冒号删除所有内容 - 这应该离开端口 - 并打印结果。

答案 1 :(得分:0)

通常,perl可以执行awkgrep可以执行的任何操作,如果跨平台操作很重要,将所有逻辑保留在一个程序中可以提供帮助(不依赖在壳上)。

这样的事可能适合你:

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

未经测试,但应该很接近。这个单行程序需要在stdin上输入netstat。

您也可以按如下方式在Perl中执行所有操作:

#!/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" }
}

答案 2 :(得分:0)

似乎最不可移植的东西是netstat调用,但是:

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

或者,坚持使用awk,它可以很容易地执行grep所做的事情:

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

将“myprocess”作为变量传递给awk脚本:

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

答案 3 :(得分:0)

要在perl中复制awk脚本行为,应该有大多数perl发行版附带的命令a2p

perl支持开箱即用的模式匹配,毫无疑问它比grep

更强大