我是Perl的新手。我编写了一个脚本来显示 Linux passwd文件中的用户名。 它显示用户名列表,但它也显示用户ID(我现在不想显示),最后显示用户ID和名称列表:"它应该在显示名称列表之前显示。 知道为什么会这样吗?
#!/usr/bin/perl
@names=system("cat /etc/passwd | cut -f 1 -d :");
@ids=system("cat /etc/passwd | cut -f 3 -d :");
$length=@ids;
$i=0;
print "List of users ids and names:\n";
while ($i < $length) {
print $names[$i];
$i +=1;
}
答案 0 :(得分:5)
简答:system
不返回命令的输出;它返回退出值。由于cut
的输出未被重定向,因此它会打印到当前的STDOUT(例如您的终端)。使用open
或qx//
引号(也称为反引号)来捕获输出:
@names = `cat /etc/passwd | cut -f 1 -d :`;
当你还在学习Perl时,这里有一篇详细介绍我如何解决这个问题的文章:
首先,始终在脚本开头use strict; use warnings;
。这有助于预防和发现许多问题,这使它成为无价的帮助。
接下来,当在Perl中完成所有事情时启动shell是低效的(您的解决方案启动了六个不必要的进程(两组sh
,cat
,cut
))。实际上,cat
即使在shell版本中也没用;只需使用shell重定向运算符:cut ... </etc/passwd
。
要在Perl中打开文件,我们将
use autodie; # automatic error handling
open my $passwd, "<", "/etc/passwd";
"<"
是模式(此处:阅读)。 $passwd
变量现在包含文件句柄,我们可以从中读取<$passwd>
之类的行。这些行仍然包含换行符,因此我们将chomp
变量(删除行结尾):
while (<$passwd>) { # <> operator reads into $_ by default
chomp; # defaults to $_
...
}
split
内置函数采用与分隔符匹配的正则表达式,字符串(默认为$_
变量)和可选限制。它返回一个字段列表。要使用:
分隔符拆分字符串,我们将执行
my @fields = split /:/;
左侧不必是数组,我们也可以提供变量列表。这与右侧的列表匹配,并为每个变量分配一个元素。如果我们想跳过某个字段,请将其命名为undef
:
my ($user, undef, $id) = split /:/;
现在我们只想打印用户。我们可以使用print
命令:
print "$user\n";
从perl5 v10开始,我们可以使用say
功能。其行为与print完全相同,但会自动在输出中附加换行符:
say $user;
瞧,我们有最后的剧本:
#!/usr/bin/perl
use strict; use warnings; use autodie; use feature 'say';
open my $passwd, "<", "/etc/passwd";
while (<$passwd>) {
chomp;
my ($user, undef, $id) = split /:/;
say $user;
}
autodie
模块作为v10.1的核心模块进行了最新的分发。此外,feature 'say'
在v10之前不可用。
因此,我们必须使用print
代替say
并执行手动错误处理:
#!/usr/bin/perl
use strict; use warnings;
open my $passwd, "<", "/etc/passwd" or die "Can't open /etc/passwd: $!";
while (<$passwd>) {
chomp;
my ($user, undef, $id) = split /:/;
print "$user\n";
}
open
失败时返回false值。在这种情况下,$!
变量将保留错误的原因。
答案 1 :(得分:3)
要读取系统数据库,您应该使用适当的系统功能:
use feature qw(say);
while (
my ($name, $passwd, $uid, $gid, $quota,
$comment, $gcos, $dir, $shell, $expire
)
= getpwent
)
{
say "$uid $name";
}
答案 2 :(得分:0)
如果您正在扫描整个密码文件,可以使用getpwent()
:
while( my @pw = getpwent() ){
print "@pw\n";
}
请参阅perldoc -f getpwent
。