验证文件中预告片中的记录计数

验证文件中预告片中的记录计数

我尝试编写一个脚本,该脚本应该验证总详细记录是否等于Record_count预告片记录,如果不匹配则抛出错误。

样本数据:

HDR9185        20210601094001202105311.11j

DTL226-42742-14                        32.389185        NM30100000178103      D207935784ZAG Desjardins Trust              CAD      5470.34       32.38A E  2.0500      5549.4420220215NESBITT BURNS INC A/C 226-42742-14 (5H94798)                                                                            C      5014.0020170215N30100000178103                5H94798   ILPYA7SM71 
                   
DTL210-86993-11                        21.979185        NM30100000187369      D207989578ZAG Desjardins Trust              CAD      5036.97       21.97N A  2.0500      5117.8120220315NESBITT BURNS INC ITF A/C 210-86993-11 (5J10948)                                                                        C      5015.0020170315N30100000187369                5J10948   ILQETLZDH1 
                  
TRL      02         93084.00

预告片记录02是记录数。

我的代码:

if ! awk -F "|" ' /^HDR/ { h++; next; } /^TRL/ {t++; next} END { exit( (h != 1) || t != 1 || $NF != NR - 2 ); }' sample.txt
then
   echo "file did not pass validation test"
   exit 1
fi
 echo "Validated successfully"

即使我的记录与预告片计数匹配或不匹配,这也会向我抛出“文件未通过验证测试”的标准输出。

答案1

您的代码似乎假设数据用作|字段分隔符,但显然没有。看来您想断言确实存在头记录 ( HDR...) 和尾记录 ( TRL) 并且尾记录提到了正确的数字,即中间数据记录 ( ) 的数量DTL...

我假设该文件可能包含空行,并且应该忽略这些空行。

awk程序:

$1 ~ /^HDR/ { h++ }
$1 ~ /^DTL/ { d++ }
$1 == "TRL" { t++; ok = (d == $2) }
END { exit !(h == 1 && t == 1 && ok) }

对于每条HDR...记录,h都会递增。对于每条DTL...记录,d都会递增。当TRL找到一条记录时,我们会递增t并计算一个布尔值,ok该值告诉我们数据行数是否正确。

如果我们END恰好遇到了一个标头和尾部记录,并且该布尔ok值为真的

如果任何记录出现乱序,以下代码还会以非零退出状态退出(同时允许零数据记录):

BEGIN { ok = 1 }
$1 ~ /^HDR/ { h++; ok = (h == 1 && d ==  0 && t == 0) }
$1 ~ /^DTL/ { d++; ok = (h == 1            && t == 0) }
$1 == "TRL" { t++; ok = (h == 1 && d == $2 && t == 1) }
!ok { exit }
END { exit !(h == 1 && t == 1 && ok) }

这可以保持布尔变量中数据的整体有效性ok,并在该变量翻转到时以非零退出状态退出错误的(或者如果仍然存在,则退出状态为零真的整个代码的运行过程)。我们仍然需要确保在到达块时恰好看到一个头记录和尾记录END,否则它将验证空文件是否正确。

要运行上述任一awk程序,请将其放入文件中(此处validate.awk)并使用

if awk -f validate.awk sample.txt; then
    echo 'file ok'
else
    echo 'file not validated'
fi

或者,在命令行上将整个程序作为单引号字符串给出:

if awk '$1 ~ /^HDR/ { h++ } $1 ~ /^DTL/ { d++ } $1 == "TRL" { t++; ok = (d == $2) } END { exit !(h == 1 && t == 1 && ok) }' sample.txt
then
    echo 'file ok'
else
    echo 'file not validated'
fi

寻址一条评论说该TRL记录可能看起来像TRL0009 93084.00where 0009is the count of all types of record。

在这种情况下,第一个awk程序可能看起来像

$1 ~ /^HDR/ { h++ }
$1 ~ /^DTL/ { d++ }
$1 ~ /^TRL/ { t++; ok = ( d == substr($0,4,4) - 2 ) }
END { exit !(h == 1 && t == 1 && ok) }

这里,substr($0,4,4)用于挑选$0(原始输入行)中从位置四开始、长度为四的字符串。我们从该数字中减去 2 以计算头记录和尾记录。

答案2

也许:

if awk -v RS='' '$1 == "TRL" {exit !($2 == (NR - 2))}' file; then
  echo "success"
else
  echo "invalid"
fi

awk 的RS = ""意思是每条记录由空行分隔(又名“段落模式”)

我最初确实对该声明有解释

exit !($2 == (NR - 2))

但你的问题中有类似的代码,所以我认为你对此没意见。反正:

  • 为了使预告片记录计数有效,整个文件必须精确地包含该计数加上标头和预告片。
  • 整个文件中的记录数是awk NR变量
  • 减去二,这应该是预告片中的计数。
  • 与 C 类似,算术比较运算符返回 1 表示成功/0 表示失败
  • shell 认为退出状态 0 表示成功,非零表示失败
  • ==所以我们否定操作符的返回码

我刚刚意识到我的代码不考虑出现的任何记录预告片,这可能会使文件无效:试试这个

if awk -v RS='' '$1 == "TRL" {n = $2} END {exit !(n == NR - 2)}' file; then ...

相关内容