我有一个看起来像这样的文件:
[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神灵而道歉。
答案 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
。