将嵌套列拆分为多列UNIX

将嵌套列拆分为多列UNIX,unix,awk,Unix,Awk,我有一个以制表符分隔的数据框,最后一列包含以“|”分隔的嵌套信息。请注意,所有行都保持这个嵌套的插入式结构,前面有'REP='1!' col1 col2 col3 col4 ID1 text text text...REP=(info1|info2|info3) ID2 text text text...REP=(info1|info2|info3) 我希望处理最后一列,以便括号内的所有信息都是一个新列: col1 col2

我有一个以制表符分隔的数据框,最后一列包含以“|”分隔的嵌套信息。请注意,所有行都保持这个嵌套的插入式结构,前面有'REP='1!'

col1    col2    col3    col4
ID1     text    text    text...REP=(info1|info2|info3)
ID2     text    text    text...REP=(info1|info2|info3)
我希望处理最后一列,以便括号内的所有信息都是一个新列:

col1    col2    col3    col4   newcol    newcol2    newcol3
ID1     text    text    text   info1     info2      info3
ID2     text    text    text   info1     info2      info3

我认为一个AWK命令会很有用,但我很难恰当地组织它。任何帮助都将不胜感激。

awk
营救

$ awk -v OFS='\t' 'NR==1{nh=NF; header=$0; next} 
                        {v=$NF; 
                         sub(/.*REP=/,"",v);
                         sub(/\.\.\.REP=.*/,"",$NF); 
                         gsub(/[()]/,"",v); 
                         n=split(v,vs,"|"); 
                         for(i=1;i<=n;i++) $(NF+i)=vs[i]} 
                   NR==2{printf "%s", header; 
                         for(i=1;i<=n;i++) printf "%s", OFS "col"(nh+i); 
                         print ""}1' file | column -t

col1  col2  col3  col4  col5   col6   col7
ID1   text  text  text  info1  info2  info3
ID2   text  text  text  info1  info2  info3
$awk-vofs='\t''NR==1{nh=NF;header=$0;next}
{v=$NF;
sub(/.*REP=/,“”,v);
sub(/\.\.REP=.*/,“”,$NF);
gsub(/[()]/,“”,v);
n=分裂(v,vs,“|”);

为了(i=1;i
awk
救援

$ awk -v OFS='\t' 'NR==1{nh=NF; header=$0; next} 
                        {v=$NF; 
                         sub(/.*REP=/,"",v);
                         sub(/\.\.\.REP=.*/,"",$NF); 
                         gsub(/[()]/,"",v); 
                         n=split(v,vs,"|"); 
                         for(i=1;i<=n;i++) $(NF+i)=vs[i]} 
                   NR==2{printf "%s", header; 
                         for(i=1;i<=n;i++) printf "%s", OFS "col"(nh+i); 
                         print ""}1' file | column -t

col1  col2  col3  col4  col5   col6   col7
ID1   text  text  text  info1  info2  info3
ID2   text  text  text  info1  info2  info3
$awk-vofs='\t''NR==1{nh=NF;header=$0;next}
{v=$NF;
sub(/.*REP=/,“”,v);
sub(/\.\.REP=.*/,“”,$NF);
gsub(/[()]/,“”,v);
n=分裂(v,vs,“|”);

对于(i=1;i
perl
one-liner,不修改标题

$ cat ip.txt 
col1    col2    col3    col4
ID1     text    text    text REP=(info1|info2|info3)
ID2     text    text    text REP=(info1|info2|info3)

$ perl -pe 's/\s*REP=\(([^)]+)\)/"\t".$1=~tr#|#\t#r/e' ip.txt
col1    col2    col3    col4
ID1     text    text    text    info1   info2   info3
ID2     text    text    text    info1   info2   info3
  • \s*REP=\([^)]+)\
    零个或多个空格,然后是
    REP(
    ,然后是捕获组以提取
    以外的字符)
    ,最后是
  • e
    modifier允许在替换部分使用Perl代码
  • $1=~tr#|#|\t#r
    将捕获组中的
    |
    更改为选项卡,然后将捕获组连接到包含选项卡的字符串

perl
一行程序不修改标题

$ cat ip.txt 
col1    col2    col3    col4
ID1     text    text    text REP=(info1|info2|info3)
ID2     text    text    text REP=(info1|info2|info3)

$ perl -pe 's/\s*REP=\(([^)]+)\)/"\t".$1=~tr#|#\t#r/e' ip.txt
col1    col2    col3    col4
ID1     text    text    text    info1   info2   info3
ID2     text    text    text    info1   info2   info3
  • \s*REP=\([^)]+)\
    零个或多个空格,然后是
    REP(
    ,然后是捕获组以提取
    以外的字符)
    ,最后是
  • e
    modifier允许在替换部分使用Perl代码
  • $1=~tr#|#|\t#r
    将捕获组中的
    |
    更改为选项卡,然后将捕获组连接到包含选项卡的字符串

这确实会在末尾留下一个标签,但可以使用额外的gsub进行修复

awk 'NR==1 {print $0,"col4\tnewcol\tnewcol2\tnewcol3")} NR>1 {gsub(/...REP=\(|\||\)/, "\t");print}' input.txt

这确实会在末尾留下一个选项卡,但可以使用额外的gsub来修复

awk 'NR==1 {print $0,"col4\tnewcol\tnewcol2\tnewcol3")} NR>1 {gsub(/...REP=\(|\||\)/, "\t");print}' input.txt

不要急于接受答案;upvote很好,如果你再等一会儿,也许会有更好的解决方案。我做这些作为快速编程练习,没有太多思考。不喜欢缩进风格,但这就是我实现它的方式。不要急于接受答案;upvote很好,也许会有更好的解决方案如果你再等一会儿,我会做一些快速编程练习。我不喜欢缩进样式,但这就是我实现它的方式。你只需要更新第一行的标题,而不是每一行:
awk'NR==1{print$0,\tnewcol1…}NR>1{gsub(/REP…/);print}“
您只需要更新第一行的标题,而不是每一行:
awk'NR==1{print$0,“\tnewcol1…”NR>1{gsub(/REP…/…);print}”
REP前面的那些点是真的存在的,还是代表更多的列?…代表col4中出现在“REP”之前的其他文本?““REP”前面有选项卡吗?”?REP前面的那些点真的在那里吗,还是代表更多的列呢?…代表col4中出现在“REP=”之前的其他文本“REP=”之前有选项卡吗?当我尝试运行此代码时,我得到一个错误,如下所示--Bareword在-e第1行,靠近-e第1行,靠近-s/\\\\\/\t/gr的位置找到了运算符预期的位置由于编译错误,-e的“s/\\\\/\t/gr”执行被中止。当我尝试运行这段代码时,我得到一个错误,如下所示——在-e第1行,靠近-e第1行的“s/\\\\\/\t/gr”语法错误,靠近-e的“s/\\\\/\t/gr”执行被中止,因为编译错误。