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
我被循环(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