如何删除第二列中第二个冒号之后的所有内容,并保留其他所有内容?

如何删除第二列中第二个冒号之后的所有内容,并保留其他所有内容?

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

相关内容