0

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

[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 的人。我没有人要问,谷歌搜索也没有成功。我提前道歉激怒了那些肯定会因为提出如此简单的问题而对我大喊大叫的perl神。

4

3 回答 3

1

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

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

但实际上,您甚至不需要遍历它。您可以直接将它们全部加入一个正则表达式:

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

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

于 2013-09-11T16:08:42.177 回答
1

使用数组来存储 的结果grep(),而不是标量。推动他们,而不是分配。否则for循环的第二次迭代将覆盖结果。就像是:

for my $el ( @ARGV ) { 
    push @specific, grep { /$el/ } @nametimes); 
};
print join "\n", @specific;
于 2013-09-11T13:56:28.683 回答
0

The easiest thing to do is to store your INI file as a structure. Then, you can go through your structure and pull out what you want. The simplest structure would be a hash of hashes. Where your heading is the key to the outer hash, and the inner hash is keyed by the parameter:

Here's is creating the basic structure:

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";
    }
}

After this, the structure will look like this:

$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'
                              }
        };

Now, all you have to do is parse your structure and pull the information you want out of it:

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

You could easily modify this last loop to skip the headings you want, or to print out the exact parameters you want.

I would also recommend using Getopt::Long to parse your command line parameters:

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

Getopt::Long could store your parameters in arrays. For example. It would put all the -include parameters in an @includes array and all the -param parameters in an @parameters array:

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

Of course, there needs to be lots of error checking (does the heading exist? What about the requested parameters?). But, this is the basic structure. Unless your file is extremely long, this is probably the easiest way to process it. If your file is extremely long, you could use the @includes and @parameters in the first loop as you read in the parameters and headings.

于 2013-09-11T16:43:52.603 回答