2012-05-25 173 views
2

我正在比较两个文件,每个文件都有一列和n行。比较两个文件中的值

文件1


亚历克斯
罗宾

文件2

阿伦
亚历
亚伦
拉尔夫
罗宾

如果文件1的数据存在于文件2中,它应该在选项卡分离的文件中返回1或0。

像这样的事情

泳0
亚历1
罗宾1

我在做什么是

#!/bin/bash 
for i in `cat file1 ` 
do 
cat file2 | awk '{ if ($1=="'$i'") print 1 ; else print 0 }'>>binary 
done 

上面的代码不给我,我是输出寻找。

请看看并建议更正。

谢谢

+0

我认为你将文件1中的所有内容与文件2中的第一行进行比较。 – alex

+0

它的集合与字典的比较,集合中的元素是否出现在字典中。 – Angelo

+0

猫的无用用途。 'awk ... < file2 >>二进制' – Jens

回答

1

下面的代码应该这样做。

仔细查看BEGINEND部分。

#!/bin/bash 
rm -f binary 
for i in $(cat file1); do 
    awk 'BEGIN {isthere=0;} { if ($1=="'$i'") isthere=1;} END { print "'$i'",isthere}' <file2>> binary 
done 
+0

输出的第二列是好的,但第一列中的值是file2中最后一个值的重复。 – Angelo

+0

是的,用“''”“ – wap26

+3

更正我调用了两遍_total_愚蠢?为file1中的每一行启动一个新的awk ...呃。 –

1

comm命令存在为您做这种比较。

下面的方法确实只有一个传球和很好地扩展到非常大的输入列表:

#!/bin/bash 
while read; do 
     if [[ $REPLY = $'\t'* ]] ; then 
       printf "%s\t0\n" "${REPLY#?}" 
     else 
       printf "%s\t1\n" "${REPLY}" 
     fi 
done < <(comm -2 <(tr '[A-Z]' '[a-z]' <file1 | sort) <(tr '[A-Z]' '[a-z]' <file2 | sort)) 

参见BashFAQ #36,这是直接点。

+0

排序后更改文件大小写有意义吗? – kojiro

+0

@kojiro好点。编辑。 –

1

有几种体面的方法。你可以简单地使用line-by-line set math

{ 
    grep -xF -f file1 file2 | sed $'s/$/\t1/' 
    grep -vxF -f file1 file2 | sed $'s/$/\t0/' 
} > somefile.txt 

另一种方法是简单地将文件,并使用uniq的-c,那么就用什么交换数字列如awk:

sort file1 file2 | uniq -c | awk '{ print $2"\t"$1 }' 
+1

组合并排序的情况不区分一个文件中的两个引用和每个文件中的一个引用 - 并且使用两个grep调用comm可以在一次传递中执行的操作(并且不必将_either_文件完全加载到内存中)似乎有点傻。 –

+0

@CharlesDuffy两个grep命令如何比两个comm命令的效率更低,再加上四个排序命令的进程替换? – kojiro

+0

在第二个例子中无用猫的使用。 'sort'直接获取文件。 –

1

另一种解决办法,如果你已经安装了python。 如果您熟悉Python并对解决方案感兴趣,则只需要一点格式。

#/bin/python 
f1 = open('file1').readlines() 
f2 = open('file2').readlines() 
f1_in_f2 = [int(x in f2) for x in f1] 
for n,c in zip(f1, f1_in_f2): 
    print n,c 
+0

如果你打算在Python中这样做,为什么不使用set算术?有本地联合和差异化操作,而且这些操作会比做这项工作的列表理解更有效率。 –

+0

是的,但你会失去原来的顺序。 – wap26

+0

它仍然更快(假设足够大的输入来克服常数因子)有一个列表和一个列表。列表中的“x in f2”是O(n)。 –

2

简单awk的解决方案:

awk 'NR==FNR{ seen[$0]=1 } NR!=FNR{ print $0 " " seen[$0] + 0}' file2 file1 

一个简单的解释:在文件2线,NR == FNR,因此执行的第一个动作,我们简单地记录这一条线一直被视为。在file1中,取得第二个动作并打印该行,后跟一个空格,后跟一个“0”或“1”,具体取决于该行是否在file2中出现。

+0

如问题所示,不匹配“Alex”和“alex”。很好的使用强制!你可以使用逗号而不是'“”'。 –

2

AWK 喜欢做这种事情。

awk 'FNR == NR {a[tolower($1)]; next} {f = 0; if (tolower($1) in a) {f = 1}; print $1, f}' file2 file1 

在参数列表中交换file2和file1的位置,使file1成为字典而不是file2。

FNR(在当前文件中的记录数)和NR(迄今的所有记录的记录数)是相等的,则所述第一文件是正在处理的一个。只需引用一个数组元素就可以实现它。这设置字典。 next指令读取下一条记录。

一旦FNRNR不相等,后续文件正在处理,他们的数据在字典数组中查找。