从perl中的数组中获取命令行参数

时间:2013-09-11 13:28:22

标签: arrays perl grep argv

我有一个看起来像这样的文件:

[options42BuySide]
logged-check-times=06:01:00
logged-check-address=192.168.3.4
logged-check-reply=192.168.2.5
logged-check-vac-days=sat,sun
start-time=06:01:00
stop-time=19:00:00
falldown=logwrite after 10000
failtolog=logwrite after 10000
listento=all
global-search-text=Target Down. This message is stored;

[stock42BuySide]
logged-check-times=06:01:00
logged-check-address=192.168.2.13
logged-check-reply=192.168.2.54
logged-check-vac-days=sat,sun
start-time=06:01:00
stop-time=18:00:00

脚本将列表研磨成名称,开始和停止时间。

sellSide40, start-time=07:05:00, stop-time=17:59:00
SellSide42, start-time=07:06:00, stop-time=17:29:00
SellSide44, start-time=07:31:00, stop-time=16:55:00
42SellSide, start-time=09:01:00, stop-time=16:59:00

问题是我想用命令行参数从文件中过滤出特定的名称。 我试图使用@ARGV数组并从@nametimes数组中获取命令行值。类似的东西:

capser@capser$ ./get_start_stop SorosSellSide42 ETFBuySide42

该脚本可以很好地解析文件 - 我只需要命令行数组的帮助

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

my ($name , $start, $stop, $specific);
my @nametimes; 
my $inifile = "/var/log/Alert.ini";
open ( my $FILE, '<', "$inifile") or die ("could not open the file -- $!");
   while(<$FILE>) {
      chomp ;
      if (/\[(\w+)\]/) {
          $name = $1;

      } elsif (/(start-time=\d+:\d+:\d+)/) {
          $start = $1;

      } elsif  (/(stop-time=\d+:\d+:\d+)/) {
          $stop = $1;
          push (@nametimes, "$name, $start, $stop");
      }
   }

for ($a = 0; $a >= $#ARGV ; $a++) {
$specific = (grep /$ARGV[$a]/, @nametimes) ;
print "$specific\n";
}

这可能很容易 - 但是我已经工作了好几天了,而且我是唯一一个在这个商店里使用perl的人。我没有人问,googlize没有淘汰。我为了激怒那些肯定会因为我提出这样简单的问题而大喊大叫的perl神灵而道歉。

3 个答案:

答案 0 :(得分:1)

使用数组存储grep()的结果,而不是标量。推它们,而不是分配。否则for循环的第二次迭代将覆盖结果。类似的东西:

for my $el ( @ARGV ) { 
    push @specific, grep { /$el/ } @nametimes); 
};
print join "\n", @specific;

答案 1 :(得分:1)

你在@ARGV上循环的构造有点笨拙 - 更常见的做法是:

for my $name (@ARGV) {
    #do something
}

但实际上,你甚至不需要循环它。您可以将它们全部直接连接到一个正则表达式中:

my $names = join("|", @ARGV);
my @matches = grep { /\b($names)\b/ } @nametimes;

我在正则表达式中使用了\ b - 表示单词边界,因此参数SellSide4与SellSide42不匹配。这可能是也可能不是你想要的......

答案 2 :(得分:0)

最简单的方法是将INI文件存储为结构。然后,您可以浏览您的结构并提取您想要的内容。最简单的结构是散列哈希。您的标题是外部哈希的关键,内部哈希由参数键入:

这是创建基本结构:

use warnings;
use strict;
use autodie;
use feature qw(say);
use Data::Dumper;

use constant INI_FILE => "test.file.txt";

open my $ini_fh, "<", INI_FILE;

my %ini_file;
my $heading;
while ( my $line = <$ini_fh> ) {
    chomp $line;
    if ( $line =~ /\[(.*)\]/ ) { #Headhing name
        $heading = $1;
    }
    elsif ( $line =~ /(.+?)\s*=\s*(.+)/ ) {
        my $parameter = $1;
        my $value     = $2;
        $ini_file{$heading}->{$parameter} = $value;
    }
    else {
        say "Invalid line $. - $line";
    }
}

在此之后,结构将如下所示:

$VAR1 = {
          'options42BuySide' => {
                                  'stop-time' => '19:00:00',
                                  'listento' => 'all',
                                  'logged-check-reply' => '192.168.2.5',
                                  'logged-check-vac-days' => 'sat,sun',
                                  'falldown' => 'logwrite after 10000',
                                  'start-time' => '06:01:00',
                                  'logged-check-address' => '192.168.3.4',
                                  'logged-check-times' => '06:01:00',
                                  'failtolog' => 'logwrite after 10000',
                                  'global-search-text' => 'Target Down. This message is stored;'
                                },
          'stock42BuySide' => {
                                'stop-time' => '18:00:00',
                                'start-time' => '06:01:00',
                                'logged-check-reply' => '192.168.2.54',
                                'logged-check-address' => '192.168.2.13',
                                'logged-check-vac-days' => 'sat,sun',
                                'logged-check-times' => '06:01:00'
                              }
        };

现在,您所要做的就是解析您的结构并从中提取您想要的信息:

for my $heading ( sort keys %ini_file ) {
    say "$heading  " . $ini_file{$heading}->{"start-time"} . "  " . $ini_file{$heading}->{"stop-time"};
}

您可以轻松修改最后一个循环以跳过所需的标题,或打印出您想要的确切参数。

我还建议使用[Getopt :: Long](http://perldoc.perl.org/Getopt/Long.html)来解析命令行参数:

my_file -include SorosSellSide42 -include ETFBuySide42 -param start-time -param stop-time

Getopt::Long可以将您的参数存储在数组中。例如。它会将所有-include参数放在@includes数组中,将所有-param参数放在@parameters数组中:

for my $heading ( @includes ) {
    print "$heading  ";
    for my $parameter ( @parameters ) {
      print "$ini_file{$heading}->{$parameter} . "   ";
    }
    print "\n;
}

当然,需要进行大量的错误检查(标题是否存在?请求的参数怎么样?)。但是,这是基本结构。除非您的文件非常长,否则这可能是处理它的最简单方法。如果您的文件非常长,则可以在读取参数和标题时在第一个循环中使用@includes@parameters