表格检查逻辑可以划分为:
1.单行逻辑的检查
将单行数据按列名存储成 field_list[col_name] = col_value
2.整表逻辑检查
将整表数据按行和列存储成 record_list[NR][col_name] = col_value
3.跨表关联检查。
高效的跨表检查,应该是通过多文件读取,将基准文件放在最前面,这样先从基准表构建索引表,然后再逐行检查外部约束。
下面直接上代码,并给出示例
框架代码 process_template.awk
- @include LIBNAME
-
- #process header
- BEGIN{
- check_fail = 0;
- }
-
- #process check
- {
- if(FNR == 1) {
- #读取文件名
- split(FILENAME, array, "/");
- filename=array[length(array)];
- #清理数组
- delete field_idx;
- delete field_list;
- delete record_list;
- #第一行读取列编号到列名的映射
- for(i=1; i <= NF; i++) {
- field_idx[i] = $i;
- }
- next;
- }
- if(FNR == 2) next;
-
- # 表格内容
- for(i=1; i <= NF; i++) {
- # 将一行数据转换为列名到列内容的映射
- field_list[field_idx[i]] = $i;
- # 记录整表数据,以行号为一级索引,列名为二级索引
- if(csvname == filename)
- record_list[FNR][field_idx[i]] = $i;
- }
-
- #check_record函数在LIBNAME这个文件中实现,处理单行数据
- rlt = check_record(field_list);
- if(rlt != "OK") {
- print "[csv check err] "filename" |line:"FNR" |err: "rlt;
- check_fail = 1;
- exit;
- }
- }
- #process end
- END{
- #check_table函数在LIBNAME这个文件中实现,处理整表数据
- rlt = check_table(record_list);
- if(rlt != "OK") {
- print "[csv check err] "csvname" |whole table|err: "rlt;
- check_fail = 1;
- }
- if(check_fail == 0) print "[check success] "csvname;
- }
逻辑实现代码示例 example.awk
- #field_list是一个map,key是列名,值是字段内容
- #函数名check_record是固定的,请不要修改
- function check_record(field_list)
- {
- if(field_list["Cost Num"] > 400)
- {
- #错误返回自定的内容
- err = "Cost Num > 400";
- return err;
- }
-
- #OK是一个固定表示,请不要修改
- err = "OK";
- return err;
- }
-
- #record_list是一个二维数组,record_list[行号][列名]=字段内容
- #函数名check_table是固定的,请不要修改
- function check_table(record_list)
- {
- for(nr in record_list)
- {
- if(isarray(record_list[nr]))
- {
- total_cost += record_list[nr]["Cost Number"];
- }
- }
-
- if(total_cost > 100)
- {
- #错误返回自定的内容
- err = "Cost Number total > 1000";
- return err;
- }
-
- #OK是一个固定表示,请不要修改
- err = "OK";
- return err;
- }
整个配置文件格式是这样的,example是csv文件的名字,每个csv对应自己的awk检查文件,文件名相同,后缀名不同
- #check_conf.ini
- example1
- example2
如上图,就会有example1.awk对应检查example1.csv,example2.awk检查example2.csv
最外部的调度脚本 check_csv.sh 是这样的:
- #!/bin/bash
- cd "$( dirname "$0" )"
-
- #单表检查逻辑
- while read line || [[ -n ${line} ]]
- do
- IFS=','
- arr=($line)
- IFS=' '
- cp ./csv_check/process_template.awk ./check_csv.awk
- sed -i "s/LIBNAME/\"csv_check\/${arr[0]}.awk\"/g" ./check_csv.awk
- gawk -F',' -v csvname="${arr[0]}.csv" -f ./check_csv.awk ${arr[0]}.csv
- done < ./csv_check/check_conf.ini
- rm -f ./check_csv.awk
执行时,将process_template.awk拷贝出来,然后替换掉其中的include文件,这样就用具体的csv检查逻辑填充了check_record和check_table