Perl将两个文本文件与公共列合并

时间:2013-12-10 09:06:29

标签: arrays perl

对Perl来说很新,这让我很头疼。 我有一个文本文件,其中包含地址,电子邮件,日期等用户特定信息。我想将此文件与/ etc / passwd文件进行比较,如果passwd文件中存在用户名,则将数组中的etc / passwd数据合并,然后进一步操作。用户命名为字母数字,如“abc123”

这是我到目前为止所做的:

    open PASSWD, "</etc/passwd" or die "$!"; # /etc/passwd file is opened to be searched for a matching username
    open INFO, "<gtc_members.txt" or die "$!"; #information.txt is opened to search for matching user name


             while (<PASSWD>) {
                    chomp;

                    my $userName = (split ":", $_)[0];
                    $homeDirectory = (split ":", $_)[5];
                    $fullName = (split ":", $_)[4];
                    $shell = (split ":", $_)[6];

                    push @userNames, ($fullName, $homeDirectory,$shell); # if $userName eq $searchName;
                    }

            while (<INFO>) {
                    chomp;
                    my $userName1 = (split ",", $_)[2];
                    $userAddress = (split ",", $_)[3];
                    $userEmail = (split ",", $_)[4];
                    $userManager = (split ",", $_)[6];

    push @userNames_1, ($userAddress,$userEmail,$userManager);# if $userName1 eq $searchName;
                    }

这就是我被困的地方。尽管尝试了不同的代码,但我无法将两个数组@userNames和@ userNames1合并到一个公共用户名上。它现在变得如此荒谬,以至于这一切都没有意义。我尝试过使用哈希,但很难匹配普通用户名,如本例所示。

3 个答案:

答案 0 :(得分:1)

首先,永远不要直接解析/etc/passwd。请改用getpw*函数。第二,目前还不清楚你要对你将要获得的数据做什么,但你可以从中得到一个想法:

perl -F, -plae'if(my($fullName, $Dir, $Shell) = (getpwnam($F[2]))[6,7,8]) {$_ .= ",$fullName,$Dir,$Shell"}' gtc_members.txt

所有/etc/passwd条目都可以通过

获得
perl -E'$,=":";say @a while @a = getpwent()'

答案 1 :(得分:1)

确实更好地使用getpw*函数来获取系统用户数据,但如果你坚持阅读/ etc / passwd,那么使用以下策略:

  1. 将/ etc / passwd读入哈希,在该哈希中存储有趣的passwd文件数据的匿名数组,因此不再需要@userNames数组。
  2. 解析INFO文件,推送有趣的字段,然后在散列中按$userName查找,如果存在 - 从存储/ etc / passwd数据的散列中推送数组。
  3. 这个例子并没有发明任何新内容,但无论如何我都要说。注意:最终数组@ userNames_1在第二次循环的evey迭代时重置。假设你在第二个循环中做了一些事情。全部放入大阵列是没用的恕我直言。但如果需要,请在my之后立即删除push,并且不会重置。 $userName在词法上是while循环块的本地,因此使用相同的名称。此外,我正在获取匿名数组作为参考,因为取消引用它@{$hash{$index}}给我“未初始化的值”错误。不确定它是否非常正确,但无论如何都可以。

    open PASSWD, "</etc/passwd" or die "$!";
    open INFO, "<gtc_members.txt" or die "$!";
    
    my %pwhash;
    
    while (<PASSWD>) {
        chomp;
        my ($userName, $fullName, $homeDirectory, $shell) = (split /:/)[0, 4, 5, 6];
        $pwhash{$userName} = [$fullName, $homeDirectory, $shell];
    }
    
    while (<INFO>) {
        chomp;
        my ($userName, $userAddress, $userEmail, $userManager) = (split /,/)[2, 3, 4, 6];
        push my @userNames_1, ($userAddress, $userEmail, $userManager);
        push @userNames_1, (@$pwinfo) if ($pwinfo = $pwhash{$userName});
        # test printout
        print join(',', @userNames_1), "\n";
    }
    

答案 2 :(得分:-1)

试试这个:

  use Data::Dumper;
  use strict;
  use warnings;
  my %users_in_passwd;
  while (<PASSWD>) {
      chomp;      
      my $userName = (split ":", $_)[0];
      my $homeDirectory = (split ":", $_)[5];
      my $fullName = (split ":", $_)[4];
      my $shell = (split ":", $_)[6];
      $users_in_passwd{$userName} = [$fullName, $homeDirectory,$shell];
  }
   while (<INFO>) {
   chomp;
       my $userName1 = (split ",", $_)[2];
       my $userAddress = (split ",", $_)[3];
       my $userEmail = (split ",", $_)[4];
       my $userManager = (split ",", $_)[6];
       if (exists  $users_in_passwd{$userName}){
          my @data_in_passwd = @{$users_in_passwd{$userName}};
          print Dumper($userName,$userName1,\@data_in_passwd,);
          ### do something
       }
   }