我使用awk / grep等比较新,想要过滤一些数据。我有一个大型电子表格,我想逐列显示唯一值。例如,我想改变这个:
DS571187 DS571220 DS571200 DS571194
contig1 contig3 contig4 contig7
contig2 contig3 contig4 contig7
contig1 contig4 contig6 contig8
contig1 contig5 contig6 contig9
contig2 contig4 contig6 contig9
contig2
contig2
看起来像这样:
DS571187 DS571220 DS571200 DS571194
contig1 contig3 contig4 contig7
contig2 contig4 contig6 contig8
contig5 contig9
基本上我正在尝试将每列排序为自己的列表,并以这种方式获取唯一值。任何帮助将不胜感激。
琥珀
答案 0 :(得分:2)
假设您的输入文件以制表符分隔,如下所示:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
for (colNr=1;colNr<=NF;colNr++) {
if (!seen[colNr,$colNr]++) {
val[++colRowNr[colNr],colNr] = $colNr
numRows = (colRowNr[colNr] > numRows ? colRowNr[colNr] : numRows)
}
}
numCols = (NF > numCols ? NF : numCols)
}
END {
for (rowNr=1;rowNr<=numRows;rowNr++) {
for (colNr=1;colNr<=numCols;colNr++) {
printf "%s%s", val[rowNr,colNr], (colNr<numCols ? OFS : ORS)
}
}
}
$ awk -f tst.awk file | column -s$'\t' -t
DS571187 DS571220 DS571200 DS571194
contig1 contig3 contig4 contig7
contig2 contig4 contig6 contig8
contig5 contig9
对column
的调用只是为了使网站上的对齐看起来很漂亮。
如果它不是制表符分隔,那么为了简洁而强健,你需要GNW awk for FIELDWIDTHS来识别中间行中可能是空的字段,就像这个输入一样(你应该测试其他潜在的解决方案,因为后面的输入列比我期望的早期版本可能会发生在你的真实数据中并使这个问题难以解决):
$ column -s$'\t' -t file
DS571187 DS571220 DS571200 DS571194
contig1 contig3 contig4 contig7
contig2 contig3 contig7
contig1 contig4 contig8
contig5 contig9
contig9
$ awk -f tst.awk file | column -s$'\t' -t
DS571187 DS571220 DS571200 DS571194
contig1 contig3 contig4 contig7
contig2 contig4 contig8
contig5 contig9
答案 1 :(得分:0)
Gawk可能需要,标签预期为分隔符,任何一个字符分隔符都有效(-F"\t"
下方):
$ cat > cs.awk
NR==1 {
nf=NF
$1=$1
print
}
NR>1 {
for(i=1;i<=NF;i++)
if($i!="")
a[i][$i]++
}
END {
for(i=1;i<=nf;i++)
n[i]=asorti(a[i])
j=asort(n)
for(i=1;i<=n[j];i++)
for(k=1;k<=nf;k++)
printf "%-8s%s", a[k][i], (k<nf?OFS:ORS)
}
$ awk -F"\t" -f cs.awk cs_by_ed.txt
DS571187 DS571220 DS571200 DS571194
contig1 contig3 contig4 contig7
contig2 contig4 contig8
contig5 contig9
答案 2 :(得分:0)
一种不同的方法,不一定有效但更容易理解。最后两行用于漂亮打印。
$ function f() { cut -d$'\t' -f$1 file1 | sed '/^$/d' | sort -u; };
paste -d$'\t' <(f 1) <(f 2) <(f 3) <(f 4) |
sed 's/\t/ \t/g' |
column -ts$'\t'
DS571187 DS571220 DS571200 DS571194
contig1 contig3 contig4 contig7
contig2 contig4 contig6 contig8
contig5 contig9