![如何删除一行中的重复值?](https://linux22.com/image/172315/%E5%A6%82%E4%BD%95%E5%88%A0%E9%99%A4%E4%B8%80%E8%A1%8C%E4%B8%AD%E7%9A%84%E9%87%8D%E5%A4%8D%E5%80%BC%EF%BC%9F.png)
我有一个这样的文件:
$ cat file
rep1 rep2
g1001_INpfu_DN44908_c3_g1 17.85 19.95
g10042/1330/2846_INpfu_DN43979_c0_g3 34.07 29.19
g1077/1457/278/278_INpfu_PRJNA287145_DN42983_c0_g1 20.69 21.64
g100/100_INpfu_DN43143_c0_g1 52.36 33.64
g79/79/79/79_INpfu_DN45068_c4_g1 58.83 74.58
第一个“_”之前的文本是组号,例如
- G 数字 _ ...
- G 1号 / 2号 _ ...
- G 1号 / 2号 / 3号 _ ...
等等(添加空格是为了便于说明。)有斜杠意味着多个组。有时一行中存在重复的组编号,我想删除它们。
预期结果应该是这样的:
rep1 rep2
g1001_INpfu_DN44908_c3_g1 17.85 19.95
g10042/1330/2846_INpfu_DN43979_c0_g3 34.07 29.19
g1077/1457/278_INpfu_PRJNA287145_DN42983_c0_g1 20.69 21.64
g100_INpfu_DN43143_c0_g1 52.36 33.64
g79_INpfu_DN45068_c4_g1 58.83 74.58
在最后三行中,相同的组号被删除,仅保留唯一的组号。
答案1
你可以尝试这样的事情,使用sed
:
$ sed -e :a -e 's:\([0-9][0-9]*\)/\1:\1:' -e ta file
rep1 rep2
g1001_INpfu_DN44908_c3_g1 17.85 19.95
g10042/1330/2846_INpfu_DN43979_c0_g3 34.07 29.19
g1077/1457/278_INpfu_PRJNA287145_DN42983_c0_g1 20.69 21.64
g100_INpfu_DN43143_c0_g1 52.36 33.64
g79_INpfu_DN45068_c4_g1 58.83 74.58
要处理部分匹配(例如g512/12/x
或g512/5120/x
不将它们转换为g512/x
and )g5120/x
,您可以在任一侧添加非数字锚点:
sed -e :a -e 's:\([^0-9]\)\([0-9][0-9]*\)/\2\([^0-9]\):\1\2\3:' -e ta file
或者使用扩展正则表达式稍微更具可读性
sed -E -e :a -e 's:([^0-9])([0-9]+)/\2([^0-9]):\1\2\3:' -e ta file
前任。给定
$ cat file
rep1 rep2
g1001_INpfu_DN44908_c3_g1 17.85 19.95
g10042/1330/2846_INpfu_DN43979_c0_g3 34.07 29.19
g1077/1457/278/278_INpfu_PRJNA287145_DN42983_c0_g1 20.69 21.64
g512/12_INpfu_DN43143_c0_g1 52.36 33.64
g100/100_INpfu_DN43143_c0_g1 52.36 33.64
g512/5120_INpfu_DN43143_c0_g1 52.36 33.64
g79/79/79/79_INpfu_DN45068_c4_g1 58.83 74.58
然后
$ sed -E -e :a -e 's:([^0-9])([0-9]+)/\2([^0-9]):\1\2\3:' -e ta file
rep1 rep2
g1001_INpfu_DN44908_c3_g1 17.85 19.95
g10042/1330/2846_INpfu_DN43979_c0_g3 34.07 29.19
g1077/1457/278_INpfu_PRJNA287145_DN42983_c0_g1 20.69 21.64
g512/12_INpfu_DN43143_c0_g1 52.36 33.64
g100_INpfu_DN43143_c0_g1 52.36 33.64
g512/5120_INpfu_DN43143_c0_g1 52.36 33.64
g79_INpfu_DN45068_c4_g1 58.83 74.58
答案2
和perl
:
perl -pe 's{^g(?:\d+/)*?(\d+)\K(?:/\1)+(?!\d)}{}' < your-file
它是严格的,因为它只会删除前导g/number/number[/number...]/number
部分中的第一个重复数字序列,并且仅当该部分后面没有数字时。
使用sed
,您可以执行相同的操作:
sed '
\|^\(g\([[:digit:]]\{1,\}/\)*[[:digit:]]\{1,\}\).*| {
h; # save a copy of original line
s||\1:|; # remove all but the leading g/x/y/z
s|\([g/]\)\([[:digit:]]\{1,\}\)\(/\2\)\{1,\}\([^[:digit:]]\)|\1\2\4|
G; # append saved copy
s|:\ng\([[:digit:]]\{1,\}/\)*[[:digit:]]\{1,\}||; # remove excess
}' < your-file