提供不可预测结果的Perl脚本

提供不可预测结果的Perl脚本,perl,Perl,我对Perl非常陌生。我编写了一个脚本来显示Linux passwd文件中的用户名。 它显示用户名列表,但同时也显示我目前不想显示的用户ID,最后显示用户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;

我对Perl非常陌生。我编写了一个脚本来显示Linux passwd文件中的用户名。 它显示用户名列表,但同时也显示我目前不想显示的用户ID,最后显示用户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;
 }
简短回答:系统不返回命令的输出;它返回退出值。由于剪切的输出没有重定向,它将打印到当前标准输出,例如您的终端。使用open或qx//quotes或backticks捕获输出:

@names = `cat /etc/passwd | cut -f 1 -d :`;
由于您仍在学习Perl,下面是一篇详细介绍如何解决该问题的文章:

第一,始终严格使用;使用警告;在脚本的开头。这有助于预防和检测许多问题,这使它成为一种无价的帮助

接下来,在Perl内部可以完成所有工作的情况下启动一个shell是低效的。您的解决方案启动了六个不必要的进程—两组sh、cat、cut。事实上,即使在shell版本中,cat也是无用的;只需使用shell重定向操作符:剪切 简短回答:系统不返回命令的输出;它返回退出值。由于剪切的输出没有重定向,它将打印到当前标准输出,例如您的终端。使用open或qx//quotes或backticks捕获输出:

@names = `cat /etc/passwd | cut -f 1 -d :`;
由于您仍在学习Perl,下面是一篇详细介绍如何解决该问题的文章:

第一,始终严格使用;使用警告;在脚本的开头。这有助于预防和检测许多问题,这使它成为一种无价的帮助


接下来,在Perl内部可以完成所有工作的情况下启动一个shell是低效的。您的解决方案启动了六个不必要的进程—两组sh、cat、cut。事实上,即使在shell版本中,cat也是无用的;只需使用shell重定向操作符:剪切 要读取系统数据库,应使用适当的系统功能:

use feature qw(say);

while (
    my ($name,    $passwd, $uid, $gid,   $quota,
        $comment, $gcos,   $dir, $shell, $expire
    )
    = getpwent
    )
{
    say "$uid $name";
}

要读取系统数据库,应使用适当的系统功能:

use feature qw(say);

while (
    my ($name,    $passwd, $uid, $gid,   $quota,
        $comment, $gcos,   $dir, $shell, $expire
    )
    = getpwent
    )
{
    say "$uid $name";
}

如果正在扫描整个密码文件,则可以使用getpwent:


请参阅perldoc-f getpwent。

如果要扫描整个密码文件,可以使用getpwent:



请参阅perldoc-f getpwent。

是否使用@id的长度来遍历@names?这对我来说似乎是个坏主意。它很好用,因为它们都是长度1;您使用@ids的长度来遍历@names?这对我来说似乎是个坏主意。它很好用,因为它们都是长度1;我最初是按照你提到的@names=cat/etc/passwd | cut-f1-d:;但当我显示$name[$I]时,它显示了确切的命令。如果你能修改并运行脚本,你会更好地理解我。Thanks@user2026794我试了一下,效果很好。你确定你没有使用普通的引号吗?你是对的,我使用了单引号。非常感谢您的详细解释,它将在未来帮助这么多人。当我运行你的脚本时,它会给我权限被拒绝的错误。我想密码文件应该有更自由的权限?@user2026794我在我的系统上测试了这个脚本,它运行正常,/etc/passwd当然有rw-r-r-as权限;所有者是根。您使用的是什么操作系统和perl-v输出的哪一行?@user2026794从不使用root,尤其是在从internet复制和粘贴代码时。还有,我对不得不使用该操作系统表示哀悼。我添加了一个更新,目标是v10之前较旧的perls。这行吗?我最初是按照你提到的@names=cat/etc/passwd | cut-f1-d:;但当我显示$name[$I]时,它显示了确切的命令。如果你能修改并运行脚本,你会更好地理解我。Thanks@user2026794我试了一下,效果很好。你确定你没有使用普通的引号吗?你是对的,我使用了单引号。非常感谢您的详细解释,它将在未来帮助这么多人。当我运行你的脚本时,它会给我权限被拒绝的错误。我想密码文件应该有更自由的权限?@user2026794我在我的系统上测试了这个脚本,它运行正常,/etc/passwd当然有rw-r-r-as权限;所有者是根。您使用的是什么操作系统和perl-v输出的哪一行?@user2026794从不使用root,尤其是在从internet复制和粘贴代码时。还有,我对不得不使用该操作系统表示哀悼。我添加了一个更新,目标是v10之前较旧的perls。这行吗?获取权限错误/b、 pl-bash:./b.pl:权限denied@user2026794如何调用脚本?perl b.pl应该工作或插入/usr/bin/perl,但不要忘记chmod+xb.pl first.Ok。你是对的。say不起作用,所以我不得不改成印刷版。我猜是perl版本问题。谢谢你的代码。say已经存在了一段时间,但是你可能需要使用特性“say”;在文件的开头打开它。不过,它只是使用隐式换行符打印。获取权限错误/b、 pl-bash:
/b.pl:许可denied@user2026794如何调用脚本?perl b.pl应该工作或插入/usr/bin/perl,但不要忘记chmod+xb.pl first.Ok。你是对的。say不起作用,所以我不得不改成印刷版。我猜是perl版本问题。谢谢你的代码。say已经存在了一段时间,但是你可能需要使用特性“say”;在文件的开头打开它。不过,它只是用隐式换行符打印出来的。
my ($user, undef, $id) = split /:/;
print "$user\n";
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;
}
#!/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";
}
use feature qw(say);

while (
    my ($name,    $passwd, $uid, $gid,   $quota,
        $comment, $gcos,   $dir, $shell, $expire
    )
    = getpwent
    )
{
    say "$uid $name";
}
while( my @pw = getpwent() ){
  print "@pw\n";
}