AWK-通过循环和条件检查处理多个文件

时间:2019-04-06 05:02:50

标签: awk

文件1:myfilename_WEEK.csv

w27_2018,257,1,26.20,0.00,24.26
w28_2018,257,1,7.97,0.00,24.26
w29_2018,257,1,34.86,0.00,24.26
w30_2018,257,1,3.29,0.00,24.26

文件2:myfilename_MONTH.csv

m07_2018,257,1,94.78,0.00,121.31
m08_2018,257,1,719.60,0.00,262.47
m09_2018,257,1,14925.60,0.00,13903.24
m10_2018,257,1,51099.66,0.00,81600.69

文件3:myfilename_HALF.csv

h02_2018,257,1,155345.19,480029.21,235802.91
h01_2019,257,1,273961.84,552545.36,140706.27
h02_2018,258,1,3250552.06,1299785.91,3697749.57
h01_2019,258,1,3582585.66,2670427.72,4009391.28

日历文件:

20180805,08/05/2018,w27_2018,WK27 2018,m07_2018,AUG 2018,q03_2018,Q03 2018,h02_2018,H02 2018,a2018,FY2018,27,WEEK 27,01,SUNDAY
20180806,08/06/2018,w27_2018,WK27 2018,m07_2018,AUG 2018,q03_2018,Q03 2018,h02_2018,H02 2018,a2018,FY2018,27,WEEK 27,02,MONDAY
...
20180811,08/11/2018,w27_2018,WK27 2018,m07_2018,AUG 2018,q03_2018,Q03 2018,h02_2018,H02 2018,a2018,FY2018,27,WEEK 27,07,SATURDAY
20180812,08/12/2018,w28_2018,WK28 2018,m07_2018,AUG 2018,q03_2018,Q03 2018,h02_2018,H02 2018,a2018,FY2018,28,WEEK 28,01,SUNDAY
..
20180816,08/16/2018,w28_2018,WK28 2018,m07_2018,AUG 2018,q03_2018,Q03 2018,h02_2018,H02 2018,a2018,FY2018,28,WEEK 28,05,THURSDAY

预期的输出(增加了换行符以提高可读性):

2018,w27_2018,WK27 2018,257,1,26.20,0.00,24.26
2018,w27_2018,WK27 2018,258,1,97192.07,9028.38,52130.32
2018,w27_2018,WK27 2018,300,1,181.44,0.00,-69.72

2018,m07_2018,AUG 2018,257,1,94.78,0.00,121.31
2018,m07_2018,AUG 2018,258,1,509253.46,45141.91,399648.71
2018,m07_2018,AUG 2018,300,1,409.10,0.00,-348.60

2018,h02_2018,H02 2018,257,1,155345.19,480029.21,235802.91
2018,h02_2018,H02 2018,258,1,3250552.06,1299785.91,3697749.57
2018,h02_2018,H02 2018,300,1,1112.93,0.00,-1164.35

我想加入所有myfilename_*以使用calendar_file添加标签和会计年度:

单个命令是:

awk -F, 'NR==FNR {a[$3]=substr($12,3,4) FS $3 FS $4; next} {print a[$1] FS $2 FS $3 FS $4 FS $5 FS $6}' calendar_file myfilename_WEEK.csv >> my_report.csv

awk -F, 'NR==FNR {a[$5]=substr($12,3,4) FS $5 FS $6; next} {print a[$1] FS $2 FS $3 FS $4 FS $5 FS $6}' calendar_file myfilename_MONTH.csv >> my_report.csv

awk -F, 'NR==FNR {a[$9]=substr($12,3,4) FS $9 FS $10; next} {print a[$1] FS $2 FS $3 FS $4 FS $5 FS $6}' calendar_file myfilename_HALF.csv >> my_report.csv

我正在尝试将所有这些都合并为一个循环:

我尝试了以下操作,但不起作用:

    for exp_file in `ls myfilename_*.csv`
     do
     awk -F, '\
     { \
        if(NR==FNR && FILENAME ~ /WEEK/) {a[$3]=substr($12,3,4) FS $3 FS $4; next} ;\
        if(NR==FNR && FILENAME ~ /MONTH/) {a[$5]=substr($12,3,4) FS $5 FS $6; next} ;\
        if(NR==FNR && FILENAME ~ /HALF/) {a[$9]=substr($12,3,4) FS $9 FS $10; next} ;\
       {print a[$1] FS $2 FS $3 FS $4 FS $5 FS $6} \
     }' calendar_file $exp_file >> my_report.csv
     done

我该如何实现?感谢您的提前帮助!

2 个答案:

答案 0 :(得分:4)

这是另一个awk解决方案,该解决方案可移植,高效且不依赖输入文件名,而是它们在命令行中给出的顺序。

awk -F ',' -v OFS=',' '
NR==FNR {
  y=substr($12,3,4)
  a[ARGV[2],$3]=y OFS $3 OFS $4  # week
  a[ARGV[3],$5]=y OFS $5 OFS $6  # month
  a[ARGV[4],$9]=y OFS $9 OFS $10 # half
  next
}
{
  $1=a[FILENAME,$1]
} 1' calendar.csv week.csv month.csv half.csv

请注意,如果您的日历文件已排序,则无需为每一行一次又一次地分析会计年度字段。在这种情况下,这样的事情会更有效:

if(p!=$12) y=substr(p=$12,3,4)

答案 1 :(得分:3)

正确的方法(GNU awk,如果您没有GNU awk,请发表评论):

awk -F, 'NR==FNR{y=substr($12,3,4); a[$3]=y FS $3 FS $4; b[$5]=y FS $5 FS $6; c[$9]=y FS $9 FS $10; next} FNR==1{printf nl;nl="\n"} match(FILENAME, /myfilename_([A-Z]*)/, f){NF=6;switch(f[1]){case "WEEK": $1=a[$1];break; case "MONTH": $1=b[$1];break; case "HALF": $1=c[$1];}}1' OFS=, calendar_file myfilename_{WEEK,MONTH,HALF}.csv

多行可读性:

awk -F, '
NR==FNR{
    y=substr($12,3,4); 
    a[$3]=y FS $3 FS $4; 
    b[$5]=y FS $5 FS $6; 
    c[$9]=y FS $9 FS $10; 
    next
} 
FNR==1{printf nl;nl=ORS} ## The newlines between sectors, if you do not need those newlines then remove this line.
match(FILENAME, /myfilename_([A-Z]*)/, f){
    NF=6;  ## To limit results for 6 columns only, can remove it here.
    switch(f[1]){
    case "WEEK": 
        $1=a[$1];
        break; 
    case "MONTH": 
        $1=b[$1];
        break; 
    case "HALF": 
        $1=c[$1];
    }
}1' OFS=, calendar_file myfilename_{WEEK,MONTH,HALF}.csv

更新:

awk -F, '
NR==FNR{
    y=substr($12,3,4); 
    a[$3]=y FS $3 FS $4; 
    b[$5]=y FS $5 FS $6; 
    c[$9]=y FS $9 FS $10; 
    next
} 
FNR==1{printf nl;nl=ORS} ## The newlines between sectors, if you do not need those newlines then remove this line.
match(FILENAME, /myfilename_([A-Z]*)/, f){
    NF=6;  ## To limit results for 6 columns only, can remove in your case.
    $1 = f[1]=="WEEK" ? a[$1] : ( f[1]=="MONTH" ? b[$1] : (f[1]=="HALF" ? c[$1] : $1) )
}1' OFS=, calendar_file myfilename_{WEEK,MONTH,HALF}.csv

第二种方式,更简洁,无需使用switch(也是GNU awk):

awk -F, '
NR==FNR{
    y=substr($12,3,4); 
    a[$3 "WEEK"]=y FS $3 FS $4; 
    a[$5 "MONTH"]=y FS $5 FS $6; 
    a[$9 "HALF"]=y FS $9 FS $10; 
    next
} 
FNR==1{printf nl;nl=ORS} ## The newlines between sectors, if you do not need those newlines then remove this line.
match(FILENAME, /myfilename_([A-Z]*)/, f){
    $1=a[$1 f[1]];
}1' OFS=, calendar_file myfilename_{WEEK,MONTH,HALF}.csv

第三种方式:如果您的数据都与它们的文件名相对应(如您在示例中显示的那样),则可以通过第三种方式消除对match的需求,从而可以处理其他awk个:

awk -F, '
NR==FNR{
    y=substr($12,3,4); 
    a[$3 "w"]=y FS $3 FS $4; 
    a[$5 "m"]=y FS $5 FS $6; 
    a[$9 "h"]=y FS $9 FS $10; 
    next
} 
FNR==1{printf nl;nl=ORS} ## The newlines between sectors, if you do not need those newlines then remove this line.
$1~/^([wmh])[0-9]{2}_[0-9]{4}/{   ## Check first fields to make sure it matches, the checking is optional if your data is all like you showed.
    $1=a[$1 substr($1,1,1)]
    print
}' OFS=, calendar_file myfilename_{WEEK,MONTH,HALF}.csv

再考虑一下,根据您的数据文件名关系,实际上不需要检查首字母(也不检查文件名):

awk -F, '
NR==FNR{
    y=substr($12,3,4); 
    a[$3]=y FS $3 FS $4; 
    a[$5]=y FS $5 FS $6; 
    a[$9]=y FS $9 FS $10; 
    next
} 
FNR==1{printf nl;nl=ORS} ## The newlines between sectors, if you do not need those newlines then remove this line.
{   ## Add  $1~/^([wmh])[0-9]{2}_[0-9]{4}/  to the beginning of this line if  you want to check and make sure first column.
    $1=a[$1]
}1' OFS=, calendar_file myfilename_{WEEK,MONTH,HALF}.csv