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

上面的代码没有给我我正在寻找的输出。

请查看并建议更正。

谢谢

4

6 回答 6

2

简单的 awk 解决方案:

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

简单解释:对于file2中的行,NR==FNR,所以执行第一个动作,我们简单记录下看到了一行。在 file1 中,执行第二个操作并打印该行,然后是一个空格,然后是“0”或“1”,具体取决于该行是否在 file2 中看到。

于 2012-05-25T13:47:04.370 回答
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不相等,后续文件将被处理,并在字典数组中查找它们的数据。

于 2012-05-25T13:47:11.733 回答
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
于 2012-05-25T13:00:47.113 回答
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,它直接在点上。

于 2012-05-25T13:06:27.907 回答
1

有几种体面的方法。您可以简单地使用逐行设置数学

{
    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 }'
于 2012-05-25T13:09:04.457 回答
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
于 2012-05-25T13:30:13.403 回答