【问题标题】:Splitting nested column to multiple columns UNIX将嵌套列拆分为多列 UNIX
【发布时间】:2016-09-30 16:08:56
【问题描述】:

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

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 命令会很有用,但在适当地构建它时遇到了麻烦。任何帮助将不胜感激。

【问题讨论】:

  • REP 之前的那些点真的存在吗,还是代表更多的列?
  • ... 表示 col4 中出现在 'REP=' 之前的附加文本
  • “REP”之前有标签吗?

标签: unix awk


【解决方案1】:

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

【讨论】:

  • 不要急于接受答案; upvote很好,如果你再等一会儿,也许会有更好的解决方案。我没有太多考虑就将这些作为速度编程练习。
  • 不喜欢缩进风格,但这正是我实现它的方式。
【解决方案2】:

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 修饰符允许在替换部分使用 Perl 代码
  • $1=~tr#|#\t#r| 更改为捕获组中的选项卡,然后将其连接到包含选项卡的字符串

【讨论】:

  • 当我尝试运行此代码时,我收到如下错误——Bareword found where operator expected at -e line 1, near "s/\|/\t/gr" 语法错误-e 第 1 行,靠近 "s/\|/\t/gr" 执行 -e 由于编译错误而中止。
【解决方案3】:

这确实会在最后留下一个标签,但可以通过额外的 gsub 来修复。

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

【讨论】:

  • 您只需要更新第一行的标题,而不是每一行:awk 'NR==1 {print $0, "\tnewcol1..."} NR&gt;1 {gsub(/REP .../...); print}'
猜你喜欢
  • 2021-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
  • 1970-01-01
  • 2012-10-20
  • 1970-01-01
相关资源
最近更新 更多