我有两个文件,如下所示:
file1
:6:66893424_T_C -0.5985 rs151222586 -0.0351 rs12364336 -0.0030 rs57502521 0.0099
file2
:6:66893424_T_C 0.5985 rs151222586 -0.0351 rs12364336 0.003 rs57502521 -0.0099
我想:
- 找到第 2 列具有相同符号(减号或加号)的行
- 创建符号匹配的 column1 条目列表
- 创建一个列 1 条目的列表,其中 不匹配
我想:
- 匹配的输出为
rs151222586
- 和一个无与伦比的输出
6:66893424_T_C rs12364336 rs57502521
答案1
并排粘贴+awk 文件,以便我们可以将第二个字段与第四个字段进行比较:
paste file1 file2 |
awk '
$2&&$4 {
print $1 > ($2*$4>0?"match":"unmatch")
}
'
结果在文件中匹配和不匹配。
答案2
处理多个输入文件是一件苦差事,如果将数据折叠到单个文件中会更容易。例如paste
或join
可以这样做:
$ paste file1 file2
6:66893424_T_C -0.5985 6:66893424_T_C 0.5985
rs151222586 -0.0351 rs151222586 -0.0351
rs12364336 -0.0030 rs12364336 0.003
rs57502521 0.0099 rs57502521 -0.0099
$ join -j1 file1 file2
6:66893424_T_C -0.5985 0.5985
rs151222586 -0.0351 -0.0351
rs12364336 -0.0030 0.003
rs57502521 0.0099 -0.0099
前者依赖于顺序正确。在这两种情况下,您可能应该检查文件是否彼此不一致。
使用 的输出paste
,符号不同的条目:
$ paste file1 file2 | awk '($2 >= 0) != ($4 >= 0) {print $1}'
6:66893424_T_C
rs12364336
rs57502521
>=
计算结果为1
or 0
,因此使用!=
类似的方法来比较比较结果。我任意选择将零对齐为正。类似地用于==
等号。
我们还可以显式定义符号函数:
$ paste file1 file2 | awk 'function sign(x) { return x >= 0 ? +1 : -1; }
sign($2) != sign($4) {print $1}'
6:66893424_T_C
rs12364336
rs57502521
答案3
由于awk
无法对两个文件执行逐行操作,因此需要一定量的缓冲。如果您的文件足够小,它就可以工作。
awk 'NR==FNR{v[$1]=$2; next}
{if ($2*v[$1]>=0) {print $1 > "matched"} else {print $1 > "unmatched"}}' file1.txt file2.txt
- 读取时
file1.txt
,只会将“标签”-“值”对记录在数组中v
,并跳到下一个输入行执行。我们是在处理file1.txt
还是file2.txt
通过检查每个文件行计数器是否FNR
等于全局行计数器来区分NR
。如果它们相等,我们正在处理第一个文件。 - 读取时
file2.txt
,会检查当前行的“value”部分与对应的值的乘积是否file1.txt
为零或正数。如果是,则它们的符号相等,并将“标签”部分输出到文件中matched
。如果为负数,则符号不相等,“标签”部分输出到文件中unmatched
。
结果:
~ > cat matched
rs151222586
~ > cat unmatched
6:66893424_T_C
rs12364336
rs57502521
笔记
- 我假设
+0
和-0
被认为具有等号。 - 我还假设不存在任何一个文件中第 2 列值为 0 而另一个文件中第 2 列值非零的行。