Bash将TSV文件中的特定列提取到新文件,并添加带有提取列标题的额外列

时间:2018-03-14 05:21:22

标签: linux bash shell csv awk

我有一个像这样的文件

name  AD01392 AV93289 AG98023 A723928
xyb323 232    3232    8992    3278
xyb897 343    434     344     3434 
xyvg87 439    3434    2434    43434

我需要将此文件中的信息提取到4个提取的单独文件中 第1列并迭代第2,3和4列,然后添加另一列,其中包含提取列的标题,如此

档案1

name  AD01392 
xyb323 232    AD01392
xyb897 343    AD01392
xyvg87 439    AD01392

文件2

name  AV93289 
xyb323 3232   AV93289
xyb897 434    AV93289  
xyvg87 3434   AV93289 

等等其他2个文件。

我可以用

提取列
awk '{print $1,$2}' file.tsv > file1.tsv
awk '{print $1,$3}' file.tsv > file2.tsv
awk '{print $1,$4}' file.tsv > file3.tsv
awk '{print $1,$5}' file.tsv > file5.tsv

但不确定如何从每列中提取第一行并将其作为列添加到所有行。

非常感谢您的帮助和贡献。

2 个答案:

答案 0 :(得分:2)

您可以使用以下内容:

awk 'NR==1{save=$2;print $1,$2}NR>1{print $1,$2,save}' file.tsv > file1.tsv
awk 'NR==1{save=$3;print $1,$3}NR>1{print $1,$3,save}' file.tsv > file2.tsv
awk 'NR==1{save=$4;print $1,$4}NR>1{print $1,$4,save}' file.tsv > file3.tsv
awk 'NR==1{save=$5;print $1,$5}NR>1{print $1,$5,save}' file.tsv > file5.tsv

打印最后一列,您只需将$2$3$4$5的内容保存在整个文件中将重复使用的tmp变量中处理。默认情况下,输出字段分隔符是空格,但您可以根据需要覆盖变量OFS的内容来更改它,因此,如果您希望将\t作为分隔符

awk 'NR==1{OFS="\t";save=$2;print $1,$2}NR>1{print $1,$2,save}' file.tsv > file1.tsv
awk 'NR==1{OFS="\t";save=$3;print $1,$3}NR>1{print $1,$3,save}' file.tsv > file2.tsv
awk 'NR==1{OFS="\t";save=$4;print $1,$4}NR>1{print $1,$4,save}' file.tsv > file3.tsv
awk 'NR==1{OFS="\t";save=$5;print $1,$5}NR>1{print $1,$5,save}' file.tsv > file5.tsv

<强>改进:

我还建议使用以下awk命令来处理文件一个且只有一个时间(假设您有一个需要2小时处理的大文件)< / p>

awk 'BEGIN{OFS="\t"}NR==1{save2=$2;save3=$3;save4=$4;save5=$5;print $1,$2> "file1.tsv";print $1,$3 > "file2.tsv"; print $1,$4 > "file3.tsv"; print $1,$5 > "file5.tsv";}NR>1{print $1,$2,save2 > "file1.tsv"; print $1,$3,save3 > "file2.tsv"; print $1,$4,save4 > "file3.tsv"; print $1,$5,save5 > 
"file5.tsv";}' file.tsv

awk代码为:

BEGIN{
    OFS="\t"
}

NR==1{
    save2=$2;
    save3=$3;
    save4=$4;
    save5=$5;
    print $1,$2> "file1.tsv";
    print $1,$3 > "file2.tsv";
    print $1,$4 > "file3.tsv";
    print $1,$5 > "file5.tsv";
}

NR>1{
    print $1,$2,save2 > "file1.tsv";
    print $1,$3,save3 > "file2.tsv";
    print $1,$4,save4 > "file3.tsv";
    print $1,$5,save5 > "file5.tsv";
}

<强>试验:

$ more file?.tsv
::::::::::::::
file1.tsv
::::::::::::::
name    AD01392
xyb323  232     AD01392
xyb897  343     AD01392
xyvg87  439     AD01392
::::::::::::::
file2.tsv
::::::::::::::
name    AV93289
xyb323  3232    AV93289
xyb897  434     AV93289
xyvg87  3434    AV93289
::::::::::::::
file3.tsv
::::::::::::::
name    AG98023
xyb323  8992    AG98023
xyb897  344     AG98023
xyvg87  2434    AG98023
::::::::::::::
file5.tsv
::::::::::::::
name    A723928
xyb323  3278    A723928
xyb897  3434    A723928
xyvg87  43434   A723928

答案 1 :(得分:2)

您能否请关注awk并告诉我这是否对您有所帮助。

awk 'FNR==1{a[1]=$1;for(i=2;i<=NF;i++){a[i]=$i;print a[1],a[i] > "File"++q;}next} {for(j=2;j<=NF;j++){print $1,$j,a[j] > "File"++o};o=""}'  Input_file

现在也添加非单线形式的解决方案。

awk '
FNR==1{
  a[1]=$1;
  for(i=2;i<=NF;i++){
    a[i]=$i;
    print a[1],a[i] > "File"++q}
  next}
{
  for(j=2;j<=NF;j++){
    print $1,$j,a[j] > "File"++o}
  o=""
}
'  Input_file