我有一个包含2000多列的分隔文件。我想通过将匹配特定模式的列移动到文件末尾来重新排列列(以及此标题下的所有行)。
我的意见:
col1:aa01 col2:aa02 col3:nn08 col4:aa03 col5:nn08 col6:aa04
value1 value2 value3 value4 value5 value6
希望以' nn08'搬到了最后:
col1:aa01 col2:aa02 col4:aa03 col6:aa04 col3:nn08 col5:nn08
value1 value2 value4 value6 value3 value5
这是我到目前为止从论坛收集的内容,但显然它不起作用:
awk 'BEGIN{FS=OFS="\t"} {a ~ /nn08/; for (i=2;i<NF; i++) $i=$(i+1); $NF=a; print}' in >out
非常感谢任何帮助。谢谢。
答案 0 :(得分:0)
使用 awk 单行
$awk 'FNR==1{ for(i=1; i<=NF; i++) if($i~/nn08/) a[i]++; } {for(i in a){str=str $i FS; $i=""} $0=$0 FS str; $1=$1; str=""}1' file
col1:aa01 col2:aa02 col4:aa03 col6:aa04 col3:nn08 col5:nn08
FNR==1{for(i=1; i<=NF; i++) if($i~/nn08/) a[i]++; }
:对于第一行,即标题,遍历每个字段,if($i~/nn08/)
为真,然后设置a[i]
的值。 a
是一个关联数组,其中i
将成为键,值将递增(如果键不存在,则最初为0)
例如。第三列a[3]=1
和类似a[5]=1
第五列。目标是将列号存储为a
中需要移位的键。
{for(i in a){str=str $i FS; $i=""} $0=$0 FS str; $1=$1; str=""}1
接下来,根据i
中存储的每个键/列字段编号a
将列值$i
附加到结束str
变量并将column
设置为{{1}即null
。循环后,将$i=""
附加到整个记录str
。
注意:$0
强制awk改造整个记录,删除在我们通过$1=$1
截断字段时创建的额外FS(空格)。
答案 1 :(得分:0)
一衬垫:
awk '{t = "";for(i=1; i<=NF; i++){if(FNR==1 && $i ~ /:nn08$/){h[i] = $i}if( i in h){t = ( t ? t OFS :"" ) $i;continue;}printf("%s%s",$i, OFS)}print t}' infile
更好的可读性:
awk '
{
t = "";
for(i=1; i<=NF; i++)
{
# store column index in array h
if(FNR==1 && $i ~ /:nn08$/){
h[i] = $i
}
# if column to be skipped then
if( i in h)
{
# concatenate variable
t = ( t ? t OFS :"" ) $i;
# continue
continue;
}
# if ok, then print such column
printf("%s%s",$i, OFS)
}
# print rest of them saved in variable
print t
}
' infile
输入:
$ cat infile
col1:aa01 col2:aa02 col3:nn08 col4:aa03 col5:nn08 col6:aa04
value1 value2 value3 value4 value5 value6
输出:
$ awk '{t = "";for(i=1; i<=NF; i++){if(FNR==1 && $i ~ /:nn08$/){h[i] = $i}if( i in h){t = ( t ? t OFS :"" ) $i;continue;}printf("%s%s",$i, OFS)}print t}' infile
col1:aa01 col2:aa02 col4:aa03 col6:aa04 col3:nn08 col5:nn08
value1 value2 value4 value6 value3 value5
答案 2 :(得分:0)
这是另一个
$ awk 'NR==1 {for(i=1;i<=NF;i++) if($i~/:nn08$/) p[i]}
{for(i=1;i<=NF;i++) if(!(i in p)) printf "%s",$i FS;
for(i in p) printf "%s",$i FS;
print ""}' file
它可以提高效率,但也许就足够了。