awk命令使用for循环打印多个列

时间:2017-05-14 11:51:56

标签: bash shell awk

我有一个文件,其中包含第1和第2列,包含项目代码和名称,然后从第3列到第12列,其中包含连续10天的消耗量。 现在我需要将其转换为10个不同的文件。在每个第1和第2列应该是相同的项目代码和项目名称,第3列将包含每天的消费量一天..

输入文件:

Code  | Name | Day1 | Day2 | Day3 |... 

10001 | abcd | 5 | 1 | 9 |...    
10002 | degg | 3 | 9 | 6 |...    
10003 | gxyz | 4 | 8 | 7 |...

我需要输出不同的文件

文件1:

Code  | Name | Day1

10001 | abcd | 5   
10002 | degg | 3   
10003 | gxyz | 4   

文件2:

Code  | Name | Day2

10001 | abcd | 1   
10002 | degg | 9   
10003 | gxyz | 8  

文件3:

Code  | Name | Day3

10001 | abcd | 9   
10002 | degg | 6   
10003 | gxyz | 7 

依旧......

我写了这样的代码

awk 'BEGIN { FS = "\t" } ; {print $1,$2,$3}' FILE_NAME > file1;
awk 'BEGIN { FS = "\t" } ; {print $1,$2,$4}' FILE_NAME > file2;
awk 'BEGIN { FS = "\t" } ; {print $1,$2,$5}' FILE_NAME > file3;

依旧......

现在我需要在' for'中编写它。或者'而'循环哪个会更快......

我不知道确切的代码,可能是这样的..

for (( i=3; i<=NF; i++)) ; do awk 'BEGIN { FS = "\t" } ; {print $1,$2,$i}' input.tsv > $i.tsv; done

请按照我的解释帮助我获得输出。

3 个答案:

答案 0 :(得分:2)

bash + 剪切 解决方案:

input.tsv 测试内容:

Code | Name | Day1 | Day2 | Day3
10001 | abcd | 5 | 1 | 9
10002 | degg | 3 | 9 | 6
10003 | gxyz | 4 | 8 | 7

day_splitter.sh 脚本:

#!/bin/bash

n=$(cat $1 | head -1 | awk -F'|' '{print NF}') # total number of fields
for ((i=3; i<=$n; i++))
do
    fn="Day"$(($i-2))  # file name containing `Day` number 
    $(cut -d'|' -f1,2,$i $1 > $fn".txt")
done

<强> 用法

bash day_splitter.sh input.tsv

<强> 结果

$cat Day1.txt
Code | Name | Day1 
10001 | abcd | 5 
10002 | degg | 3 
10003 | gxyz | 4 
$cat Day2.txt
Code | Name | Day2 
10001 | abcd | 1 
10002 | degg | 9 
10003 | gxyz | 8
$cat Day3.txt
Code | Name | Day3
10001 | abcd | 9
10002 | degg | 6
10003 | gxyz | 7

答案 1 :(得分:2)

如果你绝对需要在Bash 中使用循环,那么你的循环可以像这样修复:

for ((i = 3; i <= 10; i++)); do awk -v field=$i 'BEGIN { FS = "\t" } { print $1, $2, $field }' input.tsv > file$i.tsv; done

但是使用纯awk解决这个问题会更好,完全没有shell:

awk -v FS='\t' '
  NR == 1 {
    for (i = 3; i < NF; i++) {
      fn = "file" (i - 2) ".txt";
      print $1, $2, $i > fn;
      print "" >> fn;
    }
  }
  NR > 2 {
    for (i = 3; i < NF; i++) {
      fn = "file" (i - 2) ".txt";
      print $1, $2, $i >> fn;
    }
  }' inputfile

也就是说,当你在第一张唱片上时, 通过编写标题行和空行来创建输出文件(如问题中指定的那样)。

对于第3个及以后的记录,请附加到文件。

请注意,问题中的代码表明文件中的字段由制表符分隔,但示例文件似乎使用|填充了可变数量的空格。目前尚不清楚哪一个是你的实际案例。如果它真的以制表符分隔,则上述代码将起作用。如果实际上它是示例输入,则将第一行更改为:

awk -v OFS=' | ' -v FS='[ |]+' '

答案 2 :(得分:0)

纯粹的awk:

$ awk 'BEGIN{FS=OFS="|"}{for(i=3;i<=NF;i++) {f="file" (i-2); print $1,$2,$i >> f; close(f)}}' file

说明:

$ awk '
BEGIN {
    FS=OFS="|" }             # set delimiters
{
    for(i=3;i<=NF;i++) {     # loop the consumption fields
        f="file" (i-2)       # create the filename
        print $1,$2,$i >> f  # append to target file
        close(f) }           # close the target file
}' file