我的脚本需要帮助。我正在编写一个脚本,用于检查/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 Newbie
答案 0 :(得分:3)
关于您的代码,我有几点要指出:
使用use strict;
和use warnings;
做得很好。它们应该包含在每个perl脚本中。
选择有意义的变量名称。
$stdin
太通用了。 $username
可以更好地记录脚本的意图。
关于您的文件处理:
在您处理文件时随时添加use autodie;
。
此pragma将自动处理错误消息,并为您提供比"Error: $!\n"
更好的信息。此外,如果您想要发送手动错误消息,请务必从消息中删除新行,或die
不会报告行号。
使用词法文件句柄和open
open my $fh, '<', $password_file;
除非您需要,否则不要将整个文件加载到内存中。相反,使用while
循环并逐行处理文件
关于您的比较:@id =~ m/$stdin/
:
始终使用比较=~
comparison operator将标量绑定到模式。因此,行@id =~ m/$stdin/
实际上是将@id
的大小与您的模式进行比较:"1" =~ m/$stdin/
。这显然是一个错误。
请务必使用quotemeta
或\Q...\E
转义正则表达式特殊字符:
$list[0] =~ m/\Q$stdin/
由于您实际上想要直接相等,所以根本不要使用正则表达式,而是使用eq
仅在处理完文件的第一行后才退出。
如果你在第一行找到匹配项,你会死在一个叉子里。在你的另一个分支中,你假设其他任何一行都不匹配。
通过这些更改,我会将您的脚本更改为以下内容:
#!/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";
答案 1 :(得分:2)
#!/usr/bin/perl
use strict;
use warnings;
my $stdin = $ARGV[0];
my $password_file = '/etc/passwd';
open (PWD,"<$password_file");
my @lines = <PWD>;
my @varr = grep (m/root/, @lines);
然后检查varr数组并在需要时拆分它。
答案 2 :(得分:0)
最好使用散列进行密钥查找,但只需进行少量修改即可:
open my $in, '<', 'in.txt';
my $stdin = $ARGV[0];
while(<$in>){
chomp;
my @list = split(/\:/);
my ($id) = $list[0];
if ($id eq $stdin) {
die "Match found\n";
}
}