Perl:无法从文件中获得正确的匹配

时间:2014-08-10 16:29:46

标签: regex perl pattern-matching

我的脚本需要帮助。我正在编写一个脚本,用于检查/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

3 个答案:

答案 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";
    }
}