zoukankan      html  css  js  c++  java
  • ETL应用:使用shell实现文件级校验的方法

        BI应用中,对接口规范性约束很重要,接口文件提供需要配套提供该文件的校验文件,校验文件格式如下:

                                     需要对文件进行如下方式校验:
            采用shell方式实现如下: 
    #! /bin/bash
    #**********************************************
    #*** 程序功能:  文件级校验
    #*** 输入参数:  <数据文件路径> <校验报告路径> <接口编码> <数据日期>
    #*** 编 写 人:  
    #*** 编写日期:  
    #*** 修 改 人:  
    #*** 修改日期:  
    #**********************************************
    
    #导入常用变量
    . ./public.sh
    
    #校验成功
    readonly VERFIRY_SUCC='00'
    
    #接口文件名与规则不符,该规则目前没有做
    readonly FILE_NAME_ERR='01'
    
    #接口数据文件不存在                        
    readonly FIEL_NOT_EXISTS='02'
    
    #接口数据文件无法打开                      
    readonly FILE_OPEN_ERR='03'
                
    #文件大小不符                               
    readonly FILE_SIZE_ERR='05'
                
    #文件记录数不符                            
    readonly FILE_NUM_ERR='06'
                  
    #文件数据日期不符                          
    readonly FILE_DATE_ERR='07' 
        
    #数据文件数据日期非法                      
    readonly FILE_DATE_UNLAW='08'
    
    #数据文件记录非法结束符(非回车换行),2008-12-05新增
    readonly FILE_RS='11'
    
    #数据文件大小超过2,000,000,000Bytes         
    readonly FILE_SIZE_UNLAW='12' 
        
    #校验文件记录格式错误                      
    readonly VERF_LINE_ERR='16'
    
    #校验文件记录非法结束符(非回车换行),2008-12-05新增
    readonly VERF_RS='95'
    
    #校验文件无法打开                          
    readonly VERF_OPEN_ERR='99'
    
    #文件分隔符
    readonly FILE_SEP=''
    
    #返回值
    verf_return=${VERFIRY_SUCC}
    
    
    #***************************************************
    #** 函 数 名: if_verify()
    #** 函数功能: 判断校验文件的格式是否正确
    #** 输入参数: 校验文件名
    #***************************************************
    if_verify()
    {
    #字段数量
    field_count=0
    
    #校验文件报告文件名
    file_verf_name=$(echo "${file_verf}"|awk -F. '{print $1}')_000.verf
    
    #判断校验文件是否能打开
    if [ ! -r ${inter_path}/${file_verf} ]
     then
      printf ${file_verf}${FILE_SEP}`date +%Y%m%d%H%M%S`${FILE_SEP}${VERF_OPEN_ERR} >${report_path}/f_${file_verf_name}
      #返回值
      return 1
    else
    #判断字段数量是否符合要求
    awk -F${FILE_SEP} '{print NF}' ${inter_path}/${file_verf} |while read field_count
    do
        #判断字段个数是否是5个,如果不是返回错误
        if [ ${field_count} -ne 5 ]
         then
          printf ${file_verf}${FILE_SEP}`date +%Y%m%d%H%M%S`${FILE_SEP}${VERF_LINE_ERR} >${report_path}/f_${file_verf_name}
          #返回值
          return 1
        fi
    done
    fi
    
    #无违规项,返回0
    #return 0
    }
    
    #***************************************************
    #** 函 数 名:  date_unlawless()
    #** 函数功能:  判断时间是否合法
    #** 输入参数:  输入待检查字符
    #***************************************************
    date_unlawless()
    {
       #检查字符
       date_string=$1
       
       #字符长度
       str_length=${#date_string}
    
     
       #判断日期长度是否为6、8或10
       if [ ${str_length} -eq 6 -o ${str_length} -eq 8 -o ${str_length} -eq 10 ]
         then
           #年
            year=$(echo ${date_string}|cut -c1-4 )
           #月
            month=$(echo ${date_string}|cut -c5-6 )
         else         
            #echo 1
            return 1
       fi
    
       cal ${month} ${year} 
       #判断年月是否合法
       if [ $? -eq 1 ]
         then
            #echo 1
            return 1
       else
       
         #日期格式为YYYYMMDD
         if [ ${str_length} -ge 8 ] 
           then
              #日
              day=$(echo ${date_string}|cut -c7-8 )
           
              #小时
              hour=$(echo ${date_string}|cut -c9-10 )
           
              #当月最后一天的日期
              last_day=$(cal ${month} ${year}|sed '/^$/d'|tail -1|awk '{print $NF}' )
           
              #判断文件中的天是否大于实际天数
              if [ ${day} -gt ${last_day} ]
                 then
                   #echo 1
                   return 1
              fi
           
               #判断文件中的小时是否大于24 注:只有日期包含小时的时候,才校验小时           
               if [ ${str_length} -eq 10 ]
                 then
                     if [ ${hour} -gt 23 ]; then
                          return 1
                      fi
               fi
           fi 
        fi    
    
      # echo 0
    }
    
    #***************************************************
    #** 函 数 名:  file_verify()
    #** 函数功能:  数据文件校验内容,根据校验文件中的记录
    #**   判断数据文件是否符合规范要求
    #** 输入参数:  校验文件
    #***************************************************
    file_verify()
    {
     #校验文件名
     file_name=$1
    
     #函数返回值
     _ret_fun=0
    
     #读取校验文件中的记录
     while read LINE
     do
       verf_return=${VERFIRY_SUCC}
        
       #得到文件名
       data_file=$(echo ${LINE}|awk -F${FILE_SEP} '{print $1}')
       
       #得到校验文件名
       verf_file=$(echo "${data_file}"|sed 's/dat/verf/')
    
       #得到文件大小
       data_file_size=$(echo ${LINE}|awk -F${FILE_SEP} '{print $2}')
    
       #得到文件中包含的记录数
       data_num=$(echo ${LINE}|awk -F${FILE_SEP} '{print $3}')
    
       #得到数据日期
       data_date=$(echo ${LINE}|awk -F${FILE_SEP} '{print $4}')
    
       #得到文件生成的时间
       file_time=$(echo ${LINE}|awk -F${FILE_SEP} '{print $5}')
    
       #记录格式头
       head_str=${data_file}${FILE_SEP}`date +%Y%m%d%H%M%S`${FILE_SEP}
       
       #判断接口文件名与规则是否相符
       echo "${data_file}" | grep "${DATAFILE_PATTERN}" 1>/dev/null
       if [ $? -ne 0 ]
         then
           verf_return=${FILE_NAME_ERR}
           printf "${head_str}${verf_return}
    " >${report_path}/f_${verf_file}
           
           #函数返回值
           let "_ret_fun+=1"
    
           continue
       fi
    
       #判断数据文件是否存在
       if [ ! -f ${inter_path}/${data_file} ]
         then
           verf_return=${FIEL_NOT_EXISTS}
           printf "${head_str}${verf_return}
    " >${report_path}/f_${verf_file}
           
           #函数返回值
           let "_ret_fun+=1"
    
           continue
        fi
        
       #判断数据文件是否可以打开
       if [ ! -r ${inter_path}/${data_file} ]
         then
           verf_return=${FILE_OPEN_ERR}
           printf "${head_str}${verf_return}
    " >${report_path}/f_${verf_file}
    
           #函数返回值
           let "_ret_fun+=1"
    
           continue
       fi
    
       #实际文件大小不符
       file_fact_size=$(ls -Ll ${inter_path}/${data_file}|awk '{print $5}')
       
       #判断文件大小是否符合
       if [ ${file_fact_size} -ne ${data_file_size} ]
         then
           verf_return=${FILE_SIZE_ERR}
           printf "${head_str}${verf_return}
    " >${report_path}/f_${verf_file}
     
            #函数返回值
           let "_ret_fun+=1"
    
           continue
       fi
    
       #实际文件记录数
       file_fact_num=$(awk 'END{print NR}' ${inter_path}/${data_file})
       
       #判断文件记录数不符
       if [ ${file_fact_num} -ne ${data_num} ]
         then
           verf_return=${FILE_NUM_ERR}
           printf "${head_str}${verf_return}
    " >${report_path}/f_${verf_file}
    
           #函数返回值
           let "_ret_fun+=1"
    
           continue     
       fi
       
       #文件数据日期不符
       if [ ${data_date} -ne ${file_data_date} ] 
         then
           verf_return=${FILE_DATE_ERR}
           printf "${head_str}${verf_return}
    " >${report_path}/f_${verf_file}
    
           #函数返回值
           let "_ret_fun+=1"
    
           continue     
       fi
    
       #数据文件数据日期非法 
       date_unlawless ${data_date}
       
    
       #判断日期是否合法 
       if [ $? -ne 0 ]
         then
           verf_return=${FILE_DATE_UNLAW} 
           printf "${head_str}${verf_return}
    " >${report_path}/f_${verf_file}
    
           #函数返回值
           let "_ret_fun+=1"
    
           continue     
        fi  
    
       #数据文件大小超过2,000,000,000Bytes 
       if [ ${file_fact_size} -gt 2147483648 ] 
         then
           verf_return=${FILE_SIZE_UNLAW}
           printf "${head_str}${verf_return}
    " >${report_path}/f_${verf_file}
            
           #函数返回值
           let "_ret_fun+=1"
    
           continue     
       fi
    
       #没有检测到错误返回成功信息
       printf "${head_str}${verf_return}
    " > ${report_path}/f_${verf_file}
       #echo "${head_str}${verf_return}" > ${report_path}/f_${verf_file}
    
    done < ${file_name}
    
    #返回值
      return ${_ret_fun}
    }
    
    #***************************************************
    #** 函 数 名:  main()
    #** 函数功能: 主程序
    #** 输入参数:  数据文件路径 校验报告路径 接口编码 数据日期
    #***************************************************
    
    #判断参数是否合法
    if [ $# -ne 4 ]
      then
         echo "parameter error!"
         echo "Usage: ./file_verrify.sh <数据文件路径> <校验报告路径> <接口编码> <数据日期>"
         exit 1
    fi
    
    #初始化变量,文件路径
    inter_path=$1
    
    #校验报告文件路径
    report_path=$2
    
    #接口编码
    inter_code=$3
    
    #数据日期
    file_data_date=$4
    
    #数据文件的正则表达式配置
    DATAFILE_PATTERN="[a,i]_.*${file_data_date}_.*${inter_code}_[0-9]{2}_[0-9]{3}.dat"
    
    #校验报告路径
    if [ ! -d ${report_path} ]
     then
       #建目录
       mkdir -p ${report_path} 
    fi
    
    #提取校验文件
    if [ -z `ls ${inter_path}/*${file_data_date}_*${inter_code}_??.verf 2>/dev/null` ]; then
        echo "verify file is not exist! "
        exit 1
     else
        file_verf=$(ls ${inter_path}/*${file_data_date}_*${inter_code}_??.verf|awk -F/ '{print $NF}')
    fi
    
    #进行校验文件合法性判断
    if_verify
    
    #如果校验文件错误,不进行数据文件的校验
    if [ $? -ne 0 ]; then
        echo "verify file error! "
        exit 1
    fi
    
    #进行数据文件的校验
    file_verify ${inter_path}/${file_verf}
    if [ $? -ne 0 ]; then
        echo "data file error! "
        exit 1
    fi

                                                                

    序号

    信息内容

    数据类型及长度

    说明

    1

    接口数据文件名称

    CHAR(50)

     

    2

    文件的大小(字节数)

    NUMBER(20)

    文件的物理存储大小

    3

    文件中包含的记录数

    NUMBER(20)

     

    4

    数据日期

    CHAR(10)

    如果抽取周期为小时,则格式则格式为:YYYYMMDDHH(HH采用24小时制,取值00-23);如果抽取周期为日,则格式则格式为:YYYYMMDD;如果抽取周期为月,则格式为:YYYYMM;

    5

    文件的生成时间

    CHAR(14)

    日期格式:YYYYMMDDHH24MISS

    6

    0x0D0A

     

    行间分隔符-回车换行符

    序号

    校验结果代码

    校验结果描述

    1

    00

    校验成功

    2

    01

    接口文件名与规则不符

    3

    02

    接口数据文件不存在

    4

    03

    接口数据文件无法打开

    5

    05

    文件大小不符

    6

    06

    文件记录数不符

    7

    07

    文件数据日期不符

    8

    08

    数据文件数据日期非法

    9

    10

    数据文件接口单元编码非法

    10

    11

    数据文件记录非法结束符(非回车换行)

    11

    12

    数据文件大小超过2,000,000,000Bytes

    12

    13

    接口数据文件重复上传

    13

    14

    数据文件数据日期与期待日期不符

    14

    16

    校验文件记录格式错误

    15

    92

    校验文件数据日期与期待日期不符

    16

    93

    校验文件重复上传

    17

    94

    校验文件接口单元编码非法

    18

    95

    校验文件记录非法结束符(非回车换行)

    19

    97

    校验文件数据日期非法

    20

    98

    校验文件记录长度不符

    21

    99

    校验文件无法打开

  • 相关阅读:
    当初为蜂巢样式实验过的方法
    在看 jquery 源码中发现的一些优化方向
    我终于有案例库啦(github 提供的)
    学习笔记(五)
    试坑不完美的 clip-path (我说的 CSS 的那个)
    解决安卓机在微信上播放视频有广告问题
    requestAnimationFrame 的实验性实践
    学习笔记(四)
    ajax
    php 增删改查---增
  • 原文地址:https://www.cnblogs.com/tychyg/p/4868587.html
Copyright © 2011-2022 走看看