Perl:乘法循环,1个散列和正则表达式

时间:2015-06-17 15:30:46

标签: arrays regex perl hash perl-data-structures

我在循环(和& foreach)和AoH背后遇到了逻辑。我有关于循环和哈希数组的基本知识,但我不太清楚如何将它们组合成一个简单的解决方案。我的任务是检查普通用户的密码年龄,如果它早于 n -days(最后一部分对我来说没关系,我知道如何解决它,使用GetOptions等)。 。

为了实现这一目标,我找到了一个解决方案:

1 将文件 / etc / passwd 加载到脚本中,执行正则表达式搜索以查找常规用户。 Linux系统中的普通用户拥有1000及以上的ID,因此我使用此正则表达式来查找这些:

/(\w+)[:]x[:]1[0-9]{3}/

2 将正则表达式serch的结果加载到数组中:

my (@Usernames, %pwdsettings);
while (my $pwdsettings = <$fh2>) {
    if ($pwdsettings =~ /(\w+)[:]x[:]1[0-9]{3}/) {
    $pwdsettings{"Username"} = $1;
    push (@Usernames, \%pwdsettings);
    }
}

3 Preform chage 检查数组中的每个条目:

my $pwdsett_dump = "tmp/pwdsett-dump.txt";
...
foreach (@Usernames) {
    system("chage -l $_ > $pwdsett_dump")
}

4 打开$pwdsett_dump,然后执行第二次正则表达式搜索,以获取上次更改密码的日期。之后,将结果加载到数组(AoH)中的现有哈希:

open (my $fh3, "<", $pwdsett_dump) or die "Could not open file '$pwdsett_dump': $!";
while (my $array = <$fh3>) {
    if ($array =~ /^Last\s+password\s+change\s+:\s(\w{3})\s+(\d{2}),\s+(\d{4})/) {
        $pwdsettings{"Month"} = $1;
        $pwdsettings{"Day"} = $2;
        $pwdsettings{"Year"} = $3;
    }
}

但是,某个地方出现了严重错误。我的脚本只加载1个用户到AoH,第二个用户从未加载,我得到$VAR1->[0]

我想要的是了解如何以正确的方式创建AoH和循环。

完整脚本:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $pwdsett_dump = "tmp/pwdsett-dump.txt";
my $usernames_dump = "tmp/usernames-dump.txt";
system("cat /etc/passwd > $usernames_dump");
open (my $fh2, "<", $usernames_dump) or die "Could not open file '$usernames_dump': $!";

my (@Usernames, %pwdsettings);
while (my $pwdsettings = <$fh2>) {
    if ($pwdsettings =~ /(\w+)[:]x[:]1[0-9]{3}/) {
    $pwdsettings{"Username"} = $1;
    push (@Usernames, \%pwdsettings);
    }
}

foreach (@Usernames) {
    system("chage -l $_ > $pwdsett_dump")
}
open (my $fh3, "<", $pwdsett_dump) or die "Could not open file '$pwdsett_dump': $!";
while (my $array = <$fh3>) {
    if ($array =~ /^Last\s+password\s+change\s+:\s(\w{3})\s+(\d{2}),\s+(\d{4})/) {
    $pwdsettings{"Month"} = $1;
    $pwdsettings{"Day"} = $2;
    $pwdsettings{"Year"} = $3;
    }
}

print Dumper \@Usernames;

1 个答案:

答案 0 :(得分:0)

输出含义时需要附加文件“&gt;&gt;”而不是“&gt;”这将覆盖该文件。 system("chage -l $_ >> $pwdsett_dump")当你在循环中运行它时,每次循环执行时都会覆盖它。 使用:

foreach (@Usernames) {
    system("chage -l $_ >> $pwdsett_dump")
}
########sample script
#!/usr/bin/perl

use strict;
use warnings; 

my $usernames_dump = "/etc/passwd";
open (my $fh2, "<", $usernames_dump) or die "Could not open file '$usernames_dump': $!";

my @pwdsettings;
my $i =0;
my @pwdsett_dump;
while (<$fh2>) {

if ($_ =~ /(\w+)[:]x[:]1[0-9]{3}/) {
my @user = split(/:/, $_);
 $pwdsettings[$i] = $user[0];
 $pwdsett_dump[$i] = `chage -l $user[0]|grep Last`;
 $pwdsett_dump[$i] =~ s/Last.*://;
 $pwdsett_dump[$i] =~ s/,//;
 my @m = split(/ /,$pwdsett_dump[$i]);
 print "$user[0]\t Date: $m[2] Month: $m[1] Year: $m[3]\n";
 $i++;
   }
 }
 Output: testuser Date: 12 Month: May Year: 2015