[英]Perl merging two text files with common column
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合并到一个通用用户名上。 现在变得如此荒谬,以至于没有任何道理。 我已尝试使用哈希,但是在匹配此示例中的普通用户名时却遇到了困难。
首先,永远不要直接解析/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()'
使用getpw*
函数来获取系统用户数据确实更好,但是如果您坚持要读取/ etc / passwd,则可以使用以下策略:
@userNames
数组。 $userName
在哈希中查找,如果存在-从存储/ etc / passwd数据的哈希中推送数组。 这个例子并没有发明任何新东西,但是无论如何我还是要说。 注意:在第二个循环的遍历迭代中,将重置最终数组@ userNames_1。 假设您在第二个循环内对其进行了处理。 恕我直言,将所有内容放入大型阵列是没有用的。 但是,如果需要,请在push
后移除my
权利,并且不会被重置。 $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";
}
试试看:
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
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.