2

我想通过我的 Perl 脚本运行两个 shell 命令,该脚本find.txt使用我的模式搜索创建文件。以下是运行良好的 shell 脚本,并在从 shell 运行时给出结果:

cat "/home/atsuser/Users/srittamp/ns.conf" | grep "add\|set\|enable" | awk '{print $2}' > find.txt
grep -o '\w*' find.txt | sort | uniq > find.txt

但是,当我使用systemperl 的命令执行相同操作时,我得到一个空白find.txt. 以下是我的 Perl 脚本:

#!/usr/bin/perl

use strict;
use warnings;

my $conf_file = "/home/atsuser/Users/srittamp/ns.conf";
my $find_file = "/home/atsuser/Users/srittamp/find.txt";


system("cat \"$conf_file\" | grep \"add\\|set\\|enable\" | awk '{print \$2}' > /home/atsuser/Users/srittamp/find.txt");
system("grep -o \'\\w*\' $find_file | sort | uniq > /home/atsuser/Users/srittamp/find.txt");

谁能帮我解决这个问题?

4

5 回答 5

2

如何在 Perl 中做到这一点:

#!/usr/bin/env perl

use strict;
use warnings;

use charnames qw( :full :short );
use English qw( -no_match_vars ) ;  # Avoids regex performance penalty

my $conf_file = "/home/atsuser/Users/srittamp/ns.conf";
my $find_file = "/home/atsuser/Users/srittamp/find.txt";

# cat "/home/atsuser/Users/srittamp/ns.conf" | grep "add\|set\|enable" | awk '{print $2}' > find.txt
# grep -o '\w*' find.txt | sort | uniq > find.txt

# save unique items
my %list = ();

open my $in_fh, '<', $conf_file or die "could not open $conf_file: $OS_ERROR\n";
while( my $line = <$in_fh> ){

    # grep "add\|set\|enable"
    if( $line =~ m{ add\|set\|enable }msx ){

        # awk '{print $2}'
        my @fields = split "\N{SPACE}", $line;
        $list{ $fields[1] } = 1;

    }
}
close $in_fh or die "could not close $conf_file: $OS_ERROR\n";

# output the sorted list
open my $out_fh, '>', $find_file or die "could not open $find_file: $OS_ERROR\n";
for my $item ( sort keys %list ){
  print {$out_fh} "$item\n" or die "could not print to $find_file: $OS_ERROR\n";
}
close $in_fh or die "could not close $find_file: $OS_ERROR\n";
于 2013-07-09T13:06:42.443 回答
2

我什至不会讨论您在系统命令中对 cat 的无用使用,或者您正在定义 a 的事实$find_file,但是您不是在命令中使用变量system,而是硬编码文件路径,或者您使用的事实sort | uniq当你可以使用sort -u.

我的问题是,当您可以轻松地完成所有操作并直接在 Perl 中更高效地完成时,您为什么还要为系统命令而烦恼?:

use strict;
use warnings;
use autodie;
use feature qw(say);
use constant {
    FIND_FILE  => '/home/atsuser/Users/srittamp/find.txt',
    CONF_FILE  => '/home/atsuser/Users/srittamp/ns.conf',
};

open my $conf_fh, "<", CONF_FILE;
my %conf_hash;
while ( my $line = <$conf_fh> ) {
    chomp $line;
    next unless line =~ /add|set|enable\s+(\w+)/;
    $conf_hash{$1} = $1;
}
close $conf_fh;

open my $find_fh, ">", FIND_FILE;
for my $config ( sort keys %conf_hash ) {
    say {$find_fh} $config;
}
close $find_fh;

我不确定你在寻找什么,因为我不知道 的格式conf.ns,所以我的正则表达式匹配可能不是 100% 准确。

两个循环:第一个循环将您在散列中查找的任何内容存储为散列键。这解决了独特的问题 ( sort | uniq)。第二个只是对那些存储的密钥进行排序并将它们打印出来。

简单干净,而且可能更快。另外,我不会生成并等待其他两个进程完成,并且我的操作系统不再存在依赖问题。Solaris version ofgrep doesn't have an-o` parameter 1,而 Windows 没有这些基本的 Unix 风格命令。


1至少这不是我上次在 Solaris 上工作的时间,那是很久以前的事了。

于 2013-07-09T13:32:35.450 回答
1

一个更简单的方法来做到这一点,甚至不涉及perl,因为完成你想要的工具已经存在(虽然这样做perl或者python如果你的文件真的很大,可能会稍微更有效,但实际编写/测试/需要更多的工作正确调试):

awk '/add|set|enable/{print $2}' conf.txt | sort -u > find.txt
于 2013-07-09T15:33:08.740 回答
1

@Slaven,我将它传送到一个新文件,它现在可以工作了。非常感谢。这是代码:

\#!/usr/bin/perl

use strict;
use warnings;

my $conf_file = "/home/atsuser/Users/srittamp/ns.conf";
my $find_file = "/home/atsuser/Users/srittamp/find.txt";
my $find_file2 = "/home/atsuser/Users/srittamp/find2.txt";

system("cat \"$conf_file\" | grep \"add\\|set\\|enable\" | awk '{print \$2}' >   $find_file");
system("grep -o \'\\w*\' $find_file | sort | uniq > $find_file2");

现在 find2.txt 有正确的结果。

如果有人能提出一种更简单的方法来做到这一点,我将不胜感激。问我是 grep/awk/cat 等的新手。

谢谢,

于 2013-07-09T10:39:56.560 回答
0

这是我的配置文件:

set ns config -IPAddress 10.102.40.17 -netmask 255.255.255.0
enable ns feature WL SP LB CS SSL SSLVPN AppFw
enable ns mode L3 Edge USNIP PMTUD
set system parameter -natPcbForceFlushLimit 4294967295
set system user nsroot 114d02da8ec8def10b3fba5c29dfd9e6343484399ea3f79e3 -encrypted -timeout 0
set rsskeytype -rsstype ASYMMETRIC
set lacp -sysPriority 32768 -mac 00:30:48:b9:76:14
set ns hostName nk11p00it-nsc-ext001a
set interface 0/1 -throughput 0 -bandwidthHigh 0 -bandwidthNormal 0 -intftype "Intel 8247X" -ifnum 0/1
set interface 0/2 -throughput 0 -bandwidthHigh 0 -bandwidthNormal 0 -intftype "Intel 8247X" -ifnum 0/2
set interface 1/1 -throughput 0 -bandwidthHigh 0 -bandwidthNormal 0 -intftype "Intel 8247X" -ifnum 1/1
set interface 1/2 -throughput 0 -bandwidthHigh 0 -bandwidthNormal 0 -intftype "Intel 8247X" -ifnum 1/2
set interface 1/3 -throughput 0 -bandwidthHigh 0 -bandwidthNormal 0 -intftype "Intel 8247X" -ifnum 1/3
set interface 1/4 -throughput 0 -bandwidthHigh 0 -bandwidthNormal 0 -intftype "Intel 8247X" -ifnum 1/4

在这里,我想找到命令的第二个单词,其中“添加、设置和启用”是第一个单词。

所以,我在搜索 Add、Set、Enable 行,然后是这些行的第二个单词,最后消除了重复项。

使用该常量的问题在于,ns.conf 和我的 find.txt 存储的文件夹是在运行时动态生成的文件夹,然后在每次脚本运行结束时被删除。

例如,在我的实际脚本中,ns.conf 和 find.txt 将存储在以下文件夹中:

my $conf_file = "$SUITE_PATH/$test_instance_id/ns.conf";

其中,$test_instance_id 是在运行时创建的,它是一个唯一编号,也是该运行的文件夹名称。

于 2013-07-10T06:17:45.437 回答