我的脚本需要帮助。我正在编写一个脚本来检查用户名是否仍然存在于 /etc/passwd
中。我知道这可以在 BASH 上完成,但我想尽可能避免使用它,而只专注于使用 Perl 进行编写。
好的,所以我的问题是,我的脚本在我的 $password_file
中找不到正确的匹配项。即使它仍在文件中,我仍然收到 No root found
错误。
执行脚本。
jpd@skriv ~ $ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
jpd@skriv ~ $ ~/Copy/documents/scripts/my_perl/test.pl root
Applying pattern match (m//) to @id will act on scalar(@id) at /home/jpd/Copy/documents/scripts/my_perl/test.pl line 16.
No root found!
jpd@skriv ~ $
另外,为什么我总是收到“正在应用模式匹配...”警告?
代码如下:
#!/usr/bin/perl
use strict;
use warnings;
my $stdin = $ARGV[0];
my $password_file = '/etc/passwd';
open (PWD, $password_file) || die "Error: $!\n";
my @lines = (<PWD>);
close PWD;
for my $line (@lines) {
my @list = split /:/, $line;
my @id = "$list[0]\n";
if (@id =~ m/$stdin/) {
die "Match found!\n";
} else {
print "No $stdin found!\n";
exit 0;
}
}
提前致谢! :)
问候,
sedawkgrep
Perl 新手
最佳答案
关于您的代码,我有几点需要指出:
使用
use strict;
做得很好和use warnings;
。它们应该包含在每个 perl 脚本中。选择有意义的变量名称。
$stdin
太通用了。$username
可以更好地记录脚本的意图。关于您的文件处理:
包括
use autodie;
任何时候您处理文件时。这个编译指示会自动处理错误消息,并且会为您提供比仅仅
“Error: $!\n”
更好的信息。另外,如果您想要手动生成错误消息,请务必从消息中删除新行,否则die
将不会报告行号。使用词法文件句柄和
open
的三个参数形式open my $fh, '<', $password_file;
除非需要,否则不要将整个文件加载到内存中。相反,使用
while
循环并逐行处理文件
关于您的比较:
@id =~ m/$stdin/
:始终在比较左侧使用标量
=~
comparison operator将标量绑定(bind)到模式。因此,
@id =~ m/$stdin/
行实际上是将@id
的大小与您的模式进行比较:"1"=~ m/$stdin/
。这显然是一个错误。请务必使用
quotemeta
对正则表达式特殊字符进行转义或\Q...\E
:$list[0] =~ m/\Q$stdin/
由于您实际上想要直接相等,因此根本不要使用正则表达式,而是使用
eq
您仅在处理完文件的第一行后就退出。
在一个 fork 中,如果你在第一行找到匹配项,你就会死掉。在您的另一个分支中,您退出时假设没有其他行会匹配。
通过这些更改,我会将您的脚本更正为以下内容:
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
my $username = $ARGV[0];
my $password_file = '/etc/passwd';
open my $fh, '<', $password_file;
while (<$fh>) {
chomp;
my @cols = split /:/;
if ($cols[0] eq $username) {
die "Match found!\n";
}
}
print "No $username found!\n";
关于regex - Perl:无法从文件中获取正确的匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25230694/