我有 2 个包含 7 个字段的文件,我想根据 field1 和 field2 打印 file1 中存在但不存在于 file2 中的行。
逻辑:我想打印所有行,其中有特定的column1和column2。并且我们在file2中没有找到column1和column2的集合。示例:“sc2/10 10”您不会在文件 2 中看到该集合,因此它被打印为输出。
文件1:
sc2/80 20 . A T 86 F=5;U=4
sc2/60 55 . G T 76 F=5;U=4
sc2/10 10 . G C 50 F=5;U=4
sc2/68 20 . T C 71 F=5;U=4
sc2/24 24 . T G 31 F=5;U=4
sc2/11 30 . A T 60 F=5;U=4
文件2:
sc2/80 20 . A T 30 F=5;U=4
sc2/60 55 . T T 77 F=5;U=4
sc2/68 20 . C C 01 F=5;U=4
sc2/24 29 . T G 31 F=5;U=4
sc2/24 19 . G G 11 F=5;U=4
sc2/88 89 . T G 51 F=5;U=4
预期输出:
sc2/10 10 . G C 50 F=5;U=4
sc2/11 30 . A T 60 F=5;U=4
我将不胜感激你的帮助。
答案1
除非输入很大,否则我会将这些file2
对保存到哈希中并使用它来忽略file1
.例如:
awk 'FNR == NR { h[$1,$2]; next }; !($1 SUBSEP $2 in h)' file2 file1
输出:
sc2/10 10 . G C 50 F=5;U=4
sc2/24 24 . T G 31 F=5;U=4
sc2/11 30 . A T 60 F=5;U=4
IIUCsc2/24 24
已正确包含在输出中。
解释
FNR == NR { h[$1,$2]; next }
将对保存到散列$1/$2
中h
(请注意,通过下标访问数组足以分配它),但仅来自第一个输入文件 (file2
)。该next
命令跳至下一条记录。! ($1 SUBSEP $2 in h)
仅评估file1
并将调用行的默认块不是包含$1/$2
对。默认块是{ print $0 }
. (注意:避免使用!h[$1,$2]
(与 相同!h[$1 SUBSEP $2]
),因为这会分配它)
上面假设在文件的前两个字段中找不到 的值SUBSEP
(通常是字符)。^\
答案2
grep -Fvxf <remove> <all-lines>
- 适用于未排序的文件
- 维持秩序
- 是 POSIX
例子:
cat <<EOF > A
b
1
a
0
01
b
1
EOF
cat <<EOF > B
0
1
EOF
grep -Fvxf B A
输出:
b
a
01
b
解释:
-F
:使用文字字符串而不是默认的 BRE-x
:只考虑与整行匹配的匹配-v
: 打印不匹配-f file
:从给定文件中获取模式
此方法在预排序文件上比其他方法更慢,因为它更通用。如果速度也很重要,请参阅:https://stackoverflow.com/questions/18204904/fast-way-of-finding-lines-in-one-file-that-are-not-in-another