将嵌套列拆分为多列UNIX
我有一个以制表符分隔的数据框,最后一列包含以“|”分隔的嵌套信息。请注意,所有行都保持这个嵌套的插入式结构,前面有'REP='1!'将嵌套列拆分为多列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
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;iawk
救援
$ 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;iperl
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”执行被中止,因为编译错误。