我有4个文件,并希望知道与其他文件中的元素相比不重叠的元素(每个文件)。
档案A
Vincy
ruby
rome
档案B
Vincy
rome
Peter
档案C
Vincy
Paul
alex
文件D
Vincy
rocky
Willy
对perl,python,shell,bash中的一个衬垫有任何建议。预期的输出是:
文件A:ruby
,文件B:Peter
,文件C:Paul
,Alex
文件D:rocky
,Willy
。
答案 0 :(得分:10)
澄清问题后编辑:所有文件中的唯一元素及其出现的文件:
cat File_A File_B File_C File_D |sort | uniq -u | while read line ; do file=`grep -l $line File*` ; echo "$file $line" ; done
编辑:
如果文件很大,那么这样做的方式会更快:#!/usr/bin/perl
use strict;
use autodie;
my $wordHash ;
foreach my $arg(@ARGV){
open(my $fh, "<", $arg);
while(<$fh>){
chomp;
$wordHash->{$_}->[0] ++;
push(@{$wordHash->{$_}->[1]}, $arg);
}
}
for my $word ( keys %$wordHash ){
if($wordHash->{$word}->[0] eq 1){
print $wordHash->{$_}->[1]->[0] . ": $word\n"
}
}
执行: myscript.pl filea fileb filec ... filezz
来自澄清之前的内容: 使用shell命令很容易。所有文件中的非重复元素
cat File_A File_B File_C File_D |sort | uniq -u
所有文件中的唯一元素
cat File_A File_B File_C File_D |sort | uniq
每个文件的唯一元素 (编辑感谢@Dennis Williamson)
for line in File* ; do echo "working on $line" ; sort $line | uniq ; done
答案 1 :(得分:4)
这是一个快速的python脚本,可以对任意数量的文件执行您所要求的操作:
from sys import argv
from collections import defaultdict
filenames = argv[1:]
X = defaultdict(list)
for f in filenames:
with open(f,'r') as FIN:
for word in FIN:
X[word.strip()].append(f)
for word in X:
if len(X[word])==1:
print "Filename: %s word: %s" % (X[word][0], word)
这给出了:
Filename: D word: Willy
Filename: C word: alex
Filename: D word: rocky
Filename: C word: Paul
Filename: B word: Peter
Filename: A word: ruby
答案 2 :(得分:1)
热针:
import sys
inputs = {}
for inputFileName in sys.args[1:]:
with open(inputFileName, 'r') as inputFile:
inputs[inputFileName] = set([ line.strip() for line in inputFile ])
for inputFileName, inputSet in inputs.iteritems():
print inputFileName
result = inputSet
for otherInputFileName, otherInputSet in inputs.iteritems():
if otherInputFileName != inputFileName:
result -= otherInputSet
print result
虽然没试过; - )
答案 3 :(得分:1)
Perl单行,可读的版本,带注释:
perl -nlwe '
$a{$_}++; # count identical lines with hash
push @a, $_; # save lines in array
if (eof) { push @b,[$ARGV,@a]; @a=(); } # at eof save file name and lines
}{ # eskimo operator, executes rest of code at end of input files
for (@b) {
print shift @$_; # print file name
for (@$_) { print if $a{$_} == 1 }; # print unique lines
}
' file{A,B,C,D}.txt
注意:eof
适用于每个输入文件。
复制/粘贴版本:
perl -nlwe '$a{$_}++; push @a, $_; if (eof) { push @b,[$ARGV,@a]; @a=(); } }{ for (@b) { print shift @$_; for (@$_) { print if $a{$_} == 1 } }' file{A,B,C,D}.txt
<强>输出:强>
filea.txt
ruby
fileb.txt
Peter
filec.txt
Paul
alex
filed.txt
rocky
Willy
注意:这比预期的要复杂,而且我确信有一种方法可以让它更漂亮,但我现在就发布它,看看我是否可以清理它。