我想用 File-1
中的匹配字符串替换 File-2
中的多个字符串(超过一千个)
File-1
:
Geneid Length s1 s2
1_1 6571 7 8
1_2 5041 3 0
1_3 1032 7 3
1_4 1212 3 5
1_5 1071 3 5
2_1 7171 2 7
2_2 1038 1 1
2_3 9361 0 6
2_4 1056 5 1
File-2
(地图):
1_1
1_2 k0002
1_3
1_4
1_5 k0006
2_1
2_2
2_3
2_4 k0528
预期输出:
Geneid Length s1 s2
1_1 6571 7 8
k0002 5041 3 0
1_3 1032 7 3
1_4 1212 3 5
k0006 1071 3 5
2_1 7171 2 7
2_2 1038 1 1
2_3 9361 0 6
k0528 1056 5 1
我使用了以下 awk
命令:
awk '
NR==FNR {
a[$1]=$2
next
}
{
print (($1 in a)?a[$1]:$1, $2, $3, $4)
}' File-2 File-1 > File-3
这给了我这个:
Geneid Length s1 s2
6571 7 8
k0002 5041 3 0
1032 7 3
1212 3 5
k0006 1071 3 5
7171 2 7
1038 1 1
9361 0 6
k0528 1056 5 1
如何修改此 awk
命令以保留不匹配的字符串?
抱歉,我是 linux 新手,awk
(正在努力学习)。
答案 0 :(得分:3)
表达式 ($1 in a)?a[$1]:$1
打印 a[$1]
或 $1
取决于 $1
是否是 a
中的键。但是你所有的键都在 a
中,例如,对于键 1_1
,它打印空字符串,它是 a["1_1"]
的值。解决方案是仅在 a
中的键需要添加值时才填充 $1
。
awk 'NR==FNR { if (NF > 1) a[$1]=$2; next }
{ print (($1 in a)?a[$1]:$1, $2, $3, $4) }' File-2 File-1
为了调试像您这样的脚本,在不同点添加 print
语句以查看脚本正在执行的操作会有所帮助。以下是我最终找出您的脚本出了什么问题的方法。
# STILL BUGGY, DEBUGGING RUN
awk 'NR==FNR { print("a[" $1 "]=" $2); a[$1]=$2; next; }
{ print ($1 in a ? a[$1] : $1), $2, $3, $4, ($1 in a), a[$1], $1, ($1 in a ? "yes" : "no"), "end" }' File-2 File-1
答案 1 :(得分:2)
$ awk '
NR==FNR { if (NF>1) a[$1]=$2; next }
$1 in a { $1=a[$1] }
1' file2 file1
Geneid Length s1 s2
1_1 6571 7 8
k0002 5041 3 0
1_3 1032 7 3
1_4 1212 3 5
k0006 1071 3 5
2_1 7171 2 7
2_2 1038 1 1
2_3 9361 0 6
k0528 1056 5 1
if (NF>1)
有效地确保您只使用来自 a[]
的值填充 file2
,您需要,即具有第二个字段的值,$1 in a
确保您仅在出现以下情况时才将 $1
从 file
file2
中存在相关条目。不要测试 a[$1]==""
或
任何类似的东西都会为每个 a[]
填充 $1
在 file1 中,因此会耗尽内存并增加执行时间。1
导致打印 file1
中的当前行(可能刚刚修改)。答案 2 :(得分:1)
鉴于 File-2
不会为空:
awk 'NR==FNR{a[$1]=$2;next}a[$1]!=""{$1=a[$1]}1' File-2 File-1
Geneid Length s1 s2
1_1 6571 7 8
k0002 5041 3 0
1_3 1032 7 3
1_4 1212 3 5
k0006 1071 3 5
2_1 7171 2 7
2_2 1038 1 1
2_3 9361 0 6
k0528 1056 5 1
如果可以为空,并且使用 GNU awk
,则可以将 NR==FNR
替换为 ARGIND==1
或 FILENAME=="File-2"
。