我需要解析一个大的日志文件(平面文件),它包含两列值(列A,列B)。
两列中的值都在重复。我需要找到列A中的每个唯一值,我需要找到一组列B值。
这可以使用unix shell命令完成还是需要编写任何perl或python脚本?有什么办法可以做到?
xxxA 2
xxxA 1
xxxB 2
XXXC 3
XXXA 3
xxxD 4
xxxA - 2,1,3
xxxB - 2
xxxC - 3
xxxD - 4
答案 0 :(得分:5)
Perl'one-liner'意图/扩展,以便所有东西都适合窗口:
$ perl -F -lane '
$hash{ $F[0] }{ $F[1] }++;
} END {
for my $columnA ( keys %hash ) {
print $columnA, " - ", join( ",", keys %$hash{$columnA} ), "\n";
}
'
如果我看到原始海报的一致尝试,将会有解释。
答案 1 :(得分:3)
我会使用Python词典,其中字典键是A列值,字典值是Python内置Set type保留B列值
def parse_the_file():
lower = str.lower
split = str.split
with open('f.txt') as f:
d = {}
lines = f.read().split('\n')
for A,B in [split(l) for l in lines]:
try:
d[lower(A)].add(B)
except KeyError:
d[lower(A)] = set(B)
for a in d:
print "%s - %s" % (a,",".join(list(d[a])))
if __name__ == "__main__":
parse_the_file()
使用字典的优点是每列A值只有一个字典键。使用集合的优点是您将拥有一组唯一的B列值。
效率说明:
a = lower(A)
在输入示例上测试上面的代码会产生:
xxxd - 4
xxxa - 1,3,2
xxxb - 2
xxxc - 3
答案 2 :(得分:1)
您可以使用这个简单的多图:
class MultiMap(object):
values = {}
def __getitem__(self, index):
return self.values[index]
def __setitem__(self, index, value):
if not self.values.has_key(index):
self.values[index] = []
self.values[index].append(value)
def __repr__(self):
return repr(self.values)
查看实际操作:http://codepad.org/xOOrlbnf
答案 3 :(得分:1)
Simple Perl版本:
#!/usr/bin/perl
use strict;
use warnings;
my (%v, @row);
foreach (<DATA>) {
chomp;
$_ = lc($_);
@row = split(/\s+/, $_);
push( @{ $v{$row[0]} }, $row[1]);
}
foreach (sort keys %v) {
print "$_ - ", join( ", ", @{ $v{$_} } ), "\n";
}
__DATA__
xxxA 2
xxxA 1
xxxB 2
XXXC 3
XXXA 3
xxxD 4
没有关注变量名称。从示例中我看到它们不区分大小写。
答案 4 :(得分:0)
f = """xxxA 2
xxxA 1
xxxB 2
XXXC 3
XXXA 3
xxxD 4"""
d = {}
for line in f.split("\n"):
key, val = line.lower().split()
try:
d[key].append(val)
except KeyError:
d[key] = [val]
print d
的Python
答案 5 :(得分:0)
while() {
($key, $value) = split / /, $_;
$hash{lc($key)} = 1;
push(@array, "$key$value");
}
foreach $key (sort keys %hash) {
@arr = (grep /$key/i, @array);
chomp(@arr);
$val = join (", ", @arr);
$val =~ s#$key##gi;
print "$key\t$val\n";
}
答案 6 :(得分:0)
使用Perl oneliner:
perl -lane'$F[0]=~s/.../lc$&/e;exists$s{$F[0]}and$s{$F[0]}.=",$F[1]"or push@v,$F[0]and$s{$F[0]}=$F[1]}{print"$_ $s{$_}"for@v'
如果您的密钥区分大小写(在测试数据中不正确),则可以删除$F[0]=~s/.../lc$&/e;
;如果您可以将密钥统一到较低或较高级别,则可以使用$F[0]=lc$F[0];
或$F[0]=uc$F[0];
情况下。