根据列的内容将文件拆分为单独的文件+为每个新文件添加标题和记录总数

根据列的内容将文件拆分为单独的文件+为每个新文件添加标题和记录总数
  • 标头以 H 开头
  • 预告片以 T 开头
  • 记录以 R 开头
  • 由“|”分隔

输入文件样本

  • 预告片记录第三列是记录数,第四列是金额列的总和
  • 分割后,预告片应添加到新文件中,格式如下,包含计数和总和列
  • INPUT 记录不会遵循日期顺序。例如:第一个记录的记录为 2019-03-05,最后一条记录也是同一日期。

输入文件:

H|20200425|abcd|sum
R|abc|2019-03-05|10.00
R|abc|2019-03-05|20.00
R|abc|2019-03-06|10.00
R|abc|2019-03-05|30.00
R|abc|2019-03-06|100.00
R|abc|2019-03-06|15.00
R|abc|2019-03-06|10.00
R|abc|2019-03-05|30.00
T|20200425|8|225.00

预期产出

文件 1:应另存为20190305.txt

H|20200425|abcd|sum
R|abc|2019-03-05|10.00
R|abc|2019-03-05|20.00
R|abc|2019-03-05|30.00
R|abc|2019-03-05|30.00
T|20200425|4|90.00

文件 2:应另存为20190306.txt

H|20200425|abcd|sum
R|abc|2019-03-06|100.00
R|abc|2019-03-06|15.00
R|abc|2019-03-06|10.00
R|abc|2019-03-06|10.00
T|20200425|4|135.00

答案1

另一种awk解决方案

awk -F'[|]' '
     $1=="H"{h=$0"sum"; next}
     $1=="R"{o=$3".txt";gsub("-","",o);
           if (! sum[o]) print h > o; 
           printf ("%s|%s|%s|%.2f\n", $1, $2, $3, $4) > o; sum[o]+=$4; c[o]++}
     $1=="T"{for (o in sum) printf ("%s|%s|%d|%.2f\n", $1, $2, c[o], sum[o]) > o}' file;
tail -n +1 2019*.txt

输出

==> 20190305.txt <==
H|20200425|abcd|sum
R|abc|2019-03-05|10.00
R|abc|2019-03-05|20.00
R|abc|2019-03-05|30.00
T|20200425|3|60.00

==> 20190306.txt <==
H|20200425|abcd|sum
R|abc|2019-03-06|100.00
R|abc|2019-03-06|15.00
R|abc|2019-03-06|10.00
T|20200425|3|125.00

演练

设置FS|

awk -F'[|]' '

如果它是标题行,则捕获它,添加缺少的文本并跳转到下一行

     $1=="H"{h=$0"sum"; next}

如果它是一条记录,则抓取$3".txt"并剥离-以获取输出文件名

     $1=="R"{o=$3".txt";gsub("-","",o);

如果此输出文件的总和数组尚未初始化,则print文件头

           if (! sum[o]) print h > o; 

格式化输出,更正最后一个字段并printf保存到相关文件

           printf ("%s|%s|%s|%.2f\n", $1, $2, $3, $4) > o;

使用文件名作为索引更新此输出文件的sum记录数量c

           sum[o]+=$4; c[o]++}

如果它是尾端,则迭代总和数组以恢复与每个输出文件printf相关的文件名、撰写和摘要行o

     $1=="T"{for (o in sum) printf ("%s|%s|%d|%.2f\n", $1, $2, c[o], sum[o]) > o}' file;

显示输出

tail -n +1 2019*.txt

答案2

你可以这样做awk

if($0 ~ /^$/){next};→ 忽略空行

if(NR==1){hd=$0;h=1;next}→ 将标题存储在'高清'变量并转到下一行进行解析。

f=$3$4$5→ 将文件名存储在'F'变量(因为“-”也是一个分隔符,它的值被分隔并且可用n ${3,4,5}分别。最后在打印过程中我们附加“.txt”

awk -F'[|-]' '{
    if($0 ~ /^$/){next};
    if(NR==1){hd=$0;h=1;dt=$2;next}
    f=$3$4$5;sum+=$6;c++;
    if ( dval != f ) { h=1;printf "%s|%s|%s|%.2f\n","T",dt,c,v6 >> dval".txt";temp=$6;sum=0;c=0};
    if ($0 ~ /^T/ ) { next; }
    if ($0 ~ /^R/ ){v6=sum+temp;}
    if(h){print hd"\n\n"$0"\n" > f".txt"; h=0;}else{ print $0"\n" >> f".txt";}dval=f;
    }' inputFile

输出 :

$ cat 20190305.txt 
H|20200425|abcd|sum
R|abc|2019-03-05|10.00    
R|abc|2019-03-05|20.00
R|abc|2019-03-05|30.00
T|20200425|3|60.00

$ cat 20190306.txt 
H|20200425|abcd|sum
R|abc|2019-03-06|100.00
R|abc|2019-03-06|15.00
R|abc|2019-03-06|10.00
T|20200425|3|125.00

答案3

你可以试试这个:

awk -F'|' '
  # get the 2nd field of the header
  NR == 1 { 
    a = $2 
    h = $0
    next
  } 
  # get the date formatted
  NR == 2 { 
    d = $3; gsub(/-/,"",d) 
    print h > d
  } 
  # if the line starts with 'R', sum the column and get the count of them
  $1 == "R" { 
    sum += $4
    ++c 
  } 
  {
    print > d
  }
  # print the final line with variables acquired
  END { 
    OFS = "|"; print "T",a,c,sum".00" > d
  }
' file

输出:

$ cat 20190305.txt 
H|20200425|abcd|sum
R|abc|2019-03-05|10.00    
R|abc|2019-03-05|20.00
R|abc|2019-03-05|30.00
T|20200425|3|60.00

$ cat 20190306.txt 
H|20200425|abcd|sum
R|abc|2019-03-06|100.00
R|abc|2019-03-06|15.00
R|abc|2019-03-06|10.00
T|20200425|3|125.00

相关内容