I have file (file.bim
) with about 1.5 mill. lines that looks like this:
1 1:819959:C:T 0 819959 T C
1 1:821249:G:A 0 821249 A G
1 1:821477:A:G 0 821477 G A
1 1:821843:C:T 0 821843 T C
1 1:823963:A:C 0 823963 C A
1 1:824357:C:T 0 824357 T C
1 1:824398:A:C 0 824398 C A
1 1:827972:G:A 0 827972 A G
1 1:828539:A:T 0 828539 T A
In the second column I would like to remove the second colon and the three following characters, and keep the remaining columns as they are. The desired output is as following (updated_file.bim
):
1 1:819959 0 819959 T C
1 1:821249 0 821249 A G
1 1:821477 0 821477 G A
1 1:821843 0 821843 T C
1 1:823963 0 823963 C A
1 1:824357 0 824357 T C
1 1:824398 0 824398 C A
1 1:827972 0 827972 A G
1 1:828539 0 828539 T A
I tried using awk
, but here only the colons are removed, but the letters between them remain:
awk -F":" '{ print $1":"$2,$3,$4,$5,$6 }' file.bim > updated_file.bim
答案1
You can use the following awk
program:
awk '{sub(/:[^:]*:[^:]*$/,"",$2)}1' file.bim > updated_file.bim
or
awk '{sub(/(:[^:]*){2}$/,"",$2)}1' file.bim > updated_file.bim
这将使用该sub()
函数编辑第二列 ( $2
),将最后两列:
及其后面的文本替换为“无”,从而有效地删除该部分。
如果输出文件应以制表符分隔,请使用awk -v OFS="\t" ' ... '
.
或者,如果您的文件由以下分隔由多个“空间”组成的组并且您想确保分隔符格式完全不变,您可以使用
awk '{sub(/:[^:]*:[^: ]* /," ")}1' file.bim > updated_file.bim
它将查找模式“ :
,后跟文本,后跟:
,后跟文本,后跟空格”,并将该模式替换为单个“空格”。在您的输入中,此模式仅出现在第 2 列的末尾,因此替换只会影响该列。
最后,如果将来任何时候:
第二列中的 - 分隔字段的数量可以更改,但您仍然只想保留前两个,您可以求助于我的原来的尽管不太便携的变体,它仅用第一列周围的文本替换第二列:
(而不是最后两列后面带有“无”的文本):
awk '{$2=gensub(/([^:]+:[^:]+).*/,"\\1","1",$2)}1' file.bim > updated_file.bim
答案2
删除第二列中第二个冒号之后的所有内容并保留其他所有内容:
awk '{ c=split($2, s, ":"); $2=s[1] (c>1?":":"") s[2]; }1' infile
正如您所注意到的,如果这不是您这边的大问题,那么当我们重新评估第二列时,这会删除重复的空格;否则使用下面sed
作为替代:
sed -E 's/^([^ ]* *)([^: ]*:[^: ]*):[^ ]* (.*)/\1\2 \3/' infile
测试日期;
::1 1:81995:9:C:T 0 8::199:59 T C
1:a: :1821249GA: 0 821:2:4 A G
111 1:828539:: 0 :::828539 T A
结果:
::1 1:81995 0 8::199:59 T C
1:a: :1821249GA 0 821:2:4 A G
111 1:828539 0 :::828539 T A
答案3
使用 GNU sed 可以\S
:
$ sed 's/\(:[^:]*\)\S*/\1/' file
1 1:819959 0 819959 T C
1 1:821249 0 821249 A G
1 1:821477 0 821477 G A
1 1:821843 0 821843 T C
1 1:823963 0 823963 C A
1 1:824357 0 824357 T C
1 1:824398 0 824398 C A
1 1:827972 0 827972 A G
1 1:828539 0 828539 T A
或使用任何 POSIX sed:
$ sed 's/\(:[^:]*\)[^[:space:]]*/\1/' file
1 1:819959 0 819959 T C
1 1:821249 0 821249 A G
1 1:821477 0 821477 G A
1 1:821843 0 821843 T C
1 1:823963 0 823963 C A
1 1:824357 0 824357 T C
1 1:824398 0 824398 C A
1 1:827972 0 827972 A G
1 1:828539 0 828539 T A
答案4
首先,您awk
可以substr($2, 1, 8)
从 2 美元中选择您需要的东西。并打印 的值 s
而不是$2
。所以你的代码可以是:
awk 's = substr($2, 1, 8) {print $1, s, $3, $4, $5, $6}' file
1 1:819959 0 819959 T C
1 1:821249 0 821249 A G
1 1:821477 0 821477 G A
1 1:821843 0 821843 T C
1 1:823963 0 823963 C A
1 1:824357 0 824357 T C
1 1:824398 0 824398 C A
1 1:827972 0 827972 A G
1 1:828539 0 828539 T A
更新,以保留空格:
awk -F '[[:blank:]]{2,}' '$2 = substr($2, 1, 8) {print $1, $2, $3, $4, $5, $6}' file | column -t
1 1:819959 0 819959 T C
1 1:821249 0 821249 A G
1 1:821477 0 821477 G A
1 1:821843 0 821843 T C
1 1:823963 0 823963 C A
1 1:824357 0 824357 T C
1 1:824398 0 824398 C A
1 1:827972 0 827972 A G
1 1:828539 0 828539 T A