我有一个由制表符分隔的两列文件,如下所示:
OG0000000 PF03169,PF03169,PF03169,MAC1_004431-T1,
OG0000002 PF07690,PF00083,PF00083,PF07690,PF00083,
OG0000003 MAC1_000127-T1,
OG0000004 PF13246,PF00689,PF00690,
OG0000005 PF00012,PF01061,PF12697,PF00012,
Run Code Online (Sandbox Code Playgroud)
我只想删除第二列中的重复字符串,而不更改第一列中的任何内容,以便我的最终输出如下所示:
OG0000000 PF03169,MAC1_004431-T1,
OG0000002 PF07690,PF00083,
OG0000003 MAC1_000127-T1,
OG0000004 PF13246,PF00689,PF00690,
OG0000005 PF00012,PF01061,PF12697,
Run Code Online (Sandbox Code Playgroud)
我尝试使用 awk 来启动它。
awk 'BEGIN{RS=ORS=","} !seen[$0]++' file.txt
Run Code Online (Sandbox Code Playgroud)
但我的输出看起来像这样,如果重复的字符串首先出现,则仍然存在一些重复项。
OG0000000 PF03169,PF03169,MAC1_004431-T1,
OG0000002 PF07690,PF00083,PF07690,
OG0000003 MAC1_000127-T1,
OG0000004 PF13246,PF00689,PF00690,
OG0000005 PF00012,PF01061,PF12697,PF00012,
Run Code Online (Sandbox Code Playgroud)
我意识到问题是因为 awk 抓取的第一行是第一个逗号之前的所有内容,但我对 awk 命令仍然很粗糙,无法弄清楚如何在不弄乱第一列的情况下解决这个问题。提前致谢!
anu*_*ava 11
这awk应该适合你:
awk -F '[\t,]' '
{
printf "%s", $1 "\t"
for (i=2; i<=NF; ++i) {
if (!seen[$i]++)
printf "%s,", $i
}
print ""
delete seen
}' file
OG0000000 PF03169,MAC1_004431-T1,
OG0000002 PF07690,PF00083,
OG0000003 MAC1_000127-T1,
OG0000004 PF13246,PF00689,PF00690,
OG0000005 PF00012,PF01061,PF12697,
Run Code Online (Sandbox Code Playgroud)
PS:根据显示的预期输出,此解决方案还在每行中显示一个尾随逗号。
另一种方法是使用相同的数组$2,并为发布的非重复值的位置保留一个单独的计数器,如下所示:
awk '
{
printf "%s\t", $1
delete seen
n = split($2,arr,",")
pos = 0
for (i=1;i<=n;i++) {
if (! (arr[i] in seen)) {
printf "%s%s", pos ? "," : "", arr[i]
seen[arr[i]]=1
pos++
}
}
print ""
}
' file.txt
Run Code Online (Sandbox Code Playgroud)
示例输出
根据您的输入file.txt,输出为:
OG0000000 PF03169,MAC1_004431-T1,
OG0000002 PF07690,PF00083,
OG0000003 MAC1_000127-T1,
OG0000004 PF13246,PF00689,PF00690,
OG0000005 PF00012,PF01061,PF12697,
Run Code Online (Sandbox Code Playgroud)
根据您显示的示例和尝试,请尝试以下awk代码。我们不需要设置RS,ORS它们分别是记录分隔符和输出记录分隔符,在这个需求中我们不需要设置。将 FS 和 OFS 设置为,相应的打印字段。
awk '
BEGIN{ FS=","; OFS="\t" }
{
val=""
delete arr
num=split($2,arr,",")
for(i=1;i<=num;i++){
if(!arr[$i]++){
val=(val?val ",":"") $i
}
}
print $1,val
}
' Input_file
Run Code Online (Sandbox Code Playgroud)
这可能对你有用(GNU sed):
sed -E ':a;s/(\s+.*(\b\S+,).*)\2/\1/;ta' file
Run Code Online (Sandbox Code Playgroud)
遍历一行,删除空格后的所有重复字符串。
使用GNUsed
$ sed -E ':a;s/([^ \t]*[ \t]+)?(([[:alnum:]]+,).*)\3/\1\2/;ta' input_file
OG0000000 PF03169,MAC1_004431-T1,
OG0000002 PF07690,PF00083,
OG0000003 MAC1_000127-T1,
OG0000004 PF13246,PF00689,PF00690,
OG0000005 PF00012,PF01061,PF12697,
Run Code Online (Sandbox Code Playgroud)