表格检查逻辑可以划分为:
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