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

Perl: Multiply loops, 1 hash and regex

我被循环(while 和 foreach)和 AoH 背后的逻辑困住了。我有关于循环和散列数组的基本知识,但我不太明白如何将它们组合成一个简单的解决方案。我的任务是检查普通用户的密码期限,如果它早于 n 天(最后一部分对我来说没问题,我知道如何解决它,使用 GetOptions 等)。

为此,我想出了一个解决方案:

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

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

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

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

但是,某处出现了严重错误。我的脚本只将 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"} = ;
    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"} = ;
    $pwdsettings{"Day"} = ;
    $pwdsettings{"Year"} = ;
    }
}

print Dumper \@Usernames;

您需要在输出时附加文件,意思是使用“>>”而不是“>”,这将覆盖文件。 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