我是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;
}
Run Code Online (Sandbox Code Playgroud)
简答:system不返回命令的输出; 它返回退出值.由于cut未重定向的输出,它会打印到当前的STDOUT(例如您的终端).使用open或qx//引用(又名反引号)来捕获输出:
@names = `cat /etc/passwd | cut -f 1 -d :`;
Run Code Online (Sandbox Code Playgroud)
当您还在学习Perl时,这里有一篇文章详细说明了我如何解决这个问题:
首先,始终use strict; use warnings;在脚本的开头.这有助于预防和检测许多问题,这使它成为宝贵的帮助.
接下来,启动shell时一切都可能里面的Perl做的是低效率的(你的解决方案开始6个不必要的流程(两套sh,cat,cut)).事实上,cat即使在shell版本中也没用; 只需使用shell重定向运算符:cut ... </etc/passwd.
要在Perl中打开文件,我们会这样做
use autodie; # automatic error handling
open my $passwd, "<", "/etc/passwd";
Run Code Online (Sandbox Code Playgroud)
这"<"是模式(这里:阅读).该$passwd变量现在持有的文件句柄从中我们可以读到这样行<$passwd>.这些行仍然包含换行符,因此我们将chomp变量(删除行结尾):
while (<$passwd>) { # <> operator reads into $_ by default
chomp; # defaults to $_
...
}
Run Code Online (Sandbox Code Playgroud)
该split内建如果匹配隔板一个正则表达式,一个字符串(默认为$_变量),以及一个可选的限制.它返回一个字段列表.要用:分隔符拆分字符串,我们会这样做
my @fields = split /:/;
Run Code Online (Sandbox Code Playgroud)
左侧不必是数组,我们也可以提供变量列表.这与右侧的列表匹配,并为每个变量分配一个元素.如果我们想跳过一个字段,我们将其命名为undef:
my ($user, undef, $id) = split /:/;
Run Code Online (Sandbox Code Playgroud)
现在我们只想打印用户.我们可以使用该print命令:
print "$user\n";
Run Code Online (Sandbox Code Playgroud)
从perl5 v10开始,我们可以使用该say功能.这与print非常相似,但会自动在输出中附加换行符:
say $user;
Run Code Online (Sandbox Code Playgroud)
瞧,我们有最后的剧本:
#!/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;
}
Run Code Online (Sandbox Code Playgroud)
该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";
}
Run Code Online (Sandbox Code Playgroud)
在open返回时,它失败假值.在这种情况下,$!变量将保留错误的原因.
| 归档时间: |
|
| 查看次数: |
130 次 |
| 最近记录: |