首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将某些列中具有多个分隔条目的文件拆分为单独的行

将某些列中具有多个分隔条目的文件拆分为单独的行
EN

Stack Overflow用户
提问于 2017-06-20 12:52:57
回答 3查看 60关注 0票数 0

我有一个非常大的文件,具有以下基本格式,以及一些附加字段:

代码语言:javascript
复制
 posA,id1,id2,posB,id3,name,(n additional fields)
 1,ENST7,ENSP93,1,ENSG92,Gene1
 2,ENST25;ENST76;ENST35,ENSP91;ENSP77;ENSP78,515;544;544,ENSG765,Gene2
 3,ENST25;ENST76;ENST35,ENSP91;ENSP77;ENSP78,515;544;544,ENSG765,Gene2
 4,ENST54;ENST93,ENSP83;ENSP36,1864;722,ENSG48,Gene3
 5,ENST54;ENST93,ENSP83;ENSP36,1864;722,ENSG48,Gene3
 6,ENST54;ENST93,ENSP83;ENSP36,1864;722,ENSG48,Gene3

第一行(posA=1)每列只有一个条目,不需要修改。对于某些列具有可变数量的多个条目的行,对于第三行(posA=2),"id1“(ENST25)的第一个条目与"id2”(ENSP91)的第一个条目和"posB“(515)的第一个条目配对,依此类推,但是具有单个条目的列(例如,"posA”、"id3“、"name")适用于列2-4中的所有配对条目。除了第2-4列之外,某些字段也很少包含多个条目。

我希望将包含多个条目的列拆分为单独的行,同时保留其他列中的数据,如下所示:

代码语言:javascript
复制
 posA,id1,id2,posB,id3,name,(n additional fields)
 1,ENST7,ENSP93,1,ENSG92,Gene1
 2,ENST25,ENSP91,515,ENSG765,Gene2
 2,ENST76,ENSP77,544,ENSG765,Gene2
 2,ENST35,ENSP78,544,ENSG765,Gene2
 3,ENST25,ENSP91,515,ENSG765,Gene2
 3,ENST76,ENSP77,544,ENSG765,Gene2
 3,ENST35,ENSP78,544,ENSG765,Gene2
 4,ENST54,ENSP83,1864,ENSG48,Gene3
 4,ENST93,ENSP36,722,ENSG48,Gene3
 ...

解决这个问题的最佳方法是什么?

谢谢!

EN

回答 3

Stack Overflow用户

发布于 2017-06-20 14:24:59

以你的例子为例,最多有两个复合属性,然后使用简单的参数扩展和子字符串删除,你可以相当容易地完成你想要的,例如

代码语言:javascript
复制
#!/bin/bash

while IFS=, read -r p a1 a2 a3; do 
    [[ $a1 =~ ';' ]] && { 
        printf "%s,%s,%s,%s\n" "$p" "${a1%;*}" "${a2%;*}" "$a3"
        printf "%s,%s,%s,%s\n" "$p" "${a1#*;}" "${a2#*;}" "$a3"
    } || printf "%s,%s,%s,%s\n" "$p" "$a1" "$a2" "$a3"
done < "$1"

其中[[ $a1 =~ ';' ]]检查$a1中的';',如果找到,则使用${a1%;*}${a2%;*}提取$a1$a2中的第一个属性。然后,对于每个属性中的第二个属性,使用${a1#*;}${a2#*;}

如果$a1中不包含';',则打印属性时保持不变。IFS=,确保','上的参数是分词的。

(注意:您应该在最终脚本中添加验证文件名是否有效等内容。如果您愿意,也可以使用echo )

示例使用/输出

代码语言:javascript
复制
$ splitattrib.sh file
Pos,Attribute1,Attribute2,Attribute3
1,a,b,-
2,c,e,+
2,d,f,+
票数 0
EN

Stack Overflow用户

发布于 2017-06-20 15:30:44

假设您的多个条目用分号;分隔,下面是awk版本。

代码语言:javascript
复制
BEGIN {
    FS="[,]"
}
{
    if ($0 ~ /^[0-9].*/) {
        end_split_field = 0
        for (f=2;f<=NF;f++) {
            if ($f ~ /.*;.*/) {
                end_split_field=f
            }
        }

        if (end_split_field == 0) {
            print $0
        } else {
            for (f=2;f<=end_split_field;f++) {
                n = split($f, a, ";") #split and return the number
                for (i=1;i<=n;i++) {
                    b[f, i] = a[i]
                }
            }

            for (i=1;i<=n;i++) {
                printf $1","
                for (j=2;j<=end_split_field;j++) {
                    printf b[j, i]","
                }
                for (k=end_split_field;k<NF;k++) {
                    printf $k","
                }
                printf $NF"\n"
            }
        }
    } else {
        print $0
    }
}

将上面的内容保存为input.awk,示例输入和输出

代码语言:javascript
复制
$ cat input
Pos,Attribute1,Attribute2,Attribute3
1,a,b,-
2,c;d,e;f,+
3,g;h;i,j;k;l,-

我们可以得到分割后的输出

代码语言:javascript
复制
$ awk -f input.awk input
Pos,Attribute1,Attribute2,Attribute3
1,a,b,-
2,c,e,+
2,d,f,+
3,g,j,-
3,h,k,-
3,i,l,-
票数 0
EN

Stack Overflow用户

发布于 2017-06-22 01:35:30

最好的办法是把它分成三部分。

您有3个线型图案。一个有6列。另一个是12,最后一个是9。

6列=> 1行

12列=> 3行

9列=> 2行

您的6列不应被修改。这提醒了12和9,你可以在ifelse ifelse中将它们分开。像这样:

代码语言:javascript
复制
if( column == 6 ){...}  
else if( column == 12 ){...}  
else {...}   

下面是一个Perl单行解决方案:

代码语言:javascript
复制
perl -a -F",|;" -lne '$s=scalar @F;if($s==6){print join ",",@F}elsif($s==12){print join",",@F[0,1,4,7,-2,-1];print join",",@F[0,1,5,8,-2,-1];print join",",@F[0,1,6,9,-2,-1];}else{print join",",@F[0,1,3,5,-2,-1];print join",",@F[0,1,4,6,-2,-1]} ' file

对于您的输入,输出为:

代码语言:javascript
复制
 1,ENST7,ENSP93,1,ENSG92,Gene1
 2,ENST25,ENSP91,515,ENSG765,Gene2
 2,ENST25,ENSP77,544,ENSG765,Gene2
 2,ENST25,ENSP78,544,ENSG765,Gene2
 3,ENST25,ENSP91,515,ENSG765,Gene2
 3,ENST25,ENSP77,544,ENSG765,Gene2
 3,ENST25,ENSP78,544,ENSG765,Gene2
 4,ENST54,ENSP83,1864,ENSG48,Gene3
 4,ENST54,ENSP36,722,ENSG48,Gene3
 5,ENST54,ENSP83,1864,ENSG48,Gene3
 5,ENST54,ENSP36,722,ENSG48,Gene3
 6,ENST54,ENSP83,1864,ENSG48,Gene3
 6,ENST54,ENSP36,722,ENSG48,Gene3
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44644076

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档