Bash 检查并计数重复的行
我有一个输入数据,如:Bash 检查并计数重复的行,bash,awk,sed,duplicates,Bash,Awk,Sed,Duplicates,我有一个输入数据,如: chr17 41243232 41243373 BRCA1_ex11 chr17 41243232 41243373 BRCA1_ex12 chr17 41243471 41243644 BRCA1_ex11 chr17 41243639 41243811 BRCA1_ex11 chr13 32954112 32954208 BRCA2_ex23 chr13 32954112 329
chr17 41243232 41243373 BRCA1_ex11
chr17 41243232 41243373 BRCA1_ex12
chr17 41243471 41243644 BRCA1_ex11
chr17 41243639 41243811 BRCA1_ex11
chr13 32954112 32954208 BRCA2_ex23
chr13 32954112 32954208 BRCA2_ex24
我需要检查重复的行$2和$3行,如果是重复的,我需要合并成一行和$4列,以逗号分隔
输出:
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12
chr17 41243471 41243644 BRCA1_ex11
chr17 41243639 41243811 BRCA1_ex11
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24
chr17 41243639 41243811 BRCA1_ex11
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12
chr17 41243471 41243644 BRCA1_ex11
是否有任何AWK解决方案可以轻松处理此类数据?我将不胜感激。输入和输出是制表符分隔的格式。注:第一、第二和第三字段均相等
我的尝试是:
awk -v OFS="\t" '{i=$2 FS $1 FS $3 FS $4} {a[i]=!a[i]?$4:a[i] "," $4} END {for (l in a) {print l,a[l]}}' infile
谢谢你的建议
$ cat script.awk
{
a[$2 OFS $3] = $1 # store $1, last instance
b[$2 OFS $3] = b[$2 FS $3] $4 "," # append the $4s
}
END {
for (i in a) { # order is awk default
sub(/,$/, "", b[i]) # remove trailing ","
print a[i], i, b[i] # print
}
}
运行:
运行:
只需将第一个任务替换为
i=$1 FS $2 FS $3
并可能通过sed过滤输出,以用制表符替换空格:
... | sed 's/ / /g'
space---^ ^--- TAB
输出:
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12
chr17 41243471 41243644 BRCA1_ex11
chr17 41243639 41243811 BRCA1_ex11
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24
chr17 41243639 41243811 BRCA1_ex11
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12
chr17 41243471 41243644 BRCA1_ex11
只需将第一个任务替换为
i=$1 FS $2 FS $3
并可能通过sed过滤输出,以用制表符替换空格:
... | sed 's/ / /g'
space---^ ^--- TAB
输出:
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12
chr17 41243471 41243644 BRCA1_ex11
chr17 41243639 41243811 BRCA1_ex11
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24
chr17 41243639 41243811 BRCA1_ex11
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12
chr17 41243471 41243644 BRCA1_ex11
如果perl还可以:
-ale在空格上拆分输入行并保存到@F数组,从输入行中剥离换行符并为打印语句添加换行符
$k=join\t,@F[0..2]键可用于-前3个元素由tab连接
$h{$k}.=$h{$k}$F[3]:$F[3]根据现有值是否为空,将值追加到散列变量add
结束{print$\t$h{$\u}每个键%h}处理完所有行后,打印键和值,用制表符分隔。钥匙的顺序是随机的
使用正则表达式提取键、值的替代方法:
$ perl -nle '($k,$v)=/^(.*?)\s+(\S+)$/; $h{$k} .= $h{$k} ? ",$v" : $v; END{print "$_\t$h{$_}" foreach (keys %h) }' ip.txt
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24
chr17 41243639 41243811 BRCA1_ex11
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12
chr17 41243471 41243644 BRCA1_ex11
如果perl还可以:
-ale在空格上拆分输入行并保存到@F数组,从输入行中剥离换行符并为打印语句添加换行符
$k=join\t,@F[0..2]键可用于-前3个元素由tab连接
$h{$k}.=$h{$k}$F[3]:$F[3]根据现有值是否为空,将值追加到散列变量add
结束{print$\t$h{$\u}每个键%h}处理完所有行后,打印键和值,用制表符分隔。钥匙的顺序是随机的
使用正则表达式提取键、值的替代方法:
$ perl -nle '($k,$v)=/^(.*?)\s+(\S+)$/; $h{$k} .= $h{$k} ? ",$v" : $v; END{print "$_\t$h{$_}" foreach (keys %h) }' ip.txt
chr13 32954112 32954208 BRCA2_ex23,BRCA2_ex24
chr17 41243639 41243811 BRCA1_ex11
chr17 41243232 41243373 BRCA1_ex11,BRCA1_ex12
chr17 41243471 41243644 BRCA1_ex11
这与实际情况的区别在于:
这一次只在内存中存储一个输出行,而James'存储整个文件。
这将按行在输入中出现的顺序打印行,而James'将按随机散列顺序打印行。
这取决于您在示例中显示的键$2和$3值连续的输入,而James'将以任何顺序进行输入。
这与实际情况的区别在于:
这一次只在内存中存储一个输出行,而James'存储整个文件。
这将按行在输入中出现的顺序打印行,而James'将按随机散列顺序打印行。
这取决于您在示例中显示的键$2和$3值连续的输入,而James'将以任何顺序进行输入。
如果第一个字段不同,而第二个和第三个字段相等,该怎么办?“你自己有没有尝试过什么?”詹姆斯布朗谢谢你这个好问题。第一个字段与第二个和第三个字段相同。是的,我试着用awk学习数组,但还是自学。我将编辑我的帖子。如果第一个字段不同,而第二个和第三个字段相等怎么办?“你自己有没有尝试过什么?”詹姆斯布朗谢谢你这个好问题。第一个字段与第二个和第三个字段相同。是的,我试着用awk学习数组,但还是自学。我将编辑我的帖子。看起来这是一个伟大的工作。谢谢你,詹姆斯,看来这是一项伟大的工作。你们都有办法,詹姆斯,谢谢。