ファイルのトレーラーでレコード数を確認する

ファイルのトレーラーでレコード数を確認する

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...)と一つtail Record( TRL) および tail レコードは、正しい数値、つまり中間データ records() の数を指します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、その変数がロールオーバーされたときにゼロ以外の終了状態で終了します。間違った(またはまだ存在する場合、終了ステータス0本物完全なコード実行プロセス)。ブロックに到達するときは、正確に1つのヘッドレコードとテールレコードが表示されていることを確認する必要があります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.000009

この場合、最初のawkプログラムは次のようになります。

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

ここでは、(元の入力行)の位置4から始まり、長さ4の文字列を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 変数です。
  • マイナス2は予告編のカウントでなければなりません。
  • Cと同様に、算術比較演算子は成功した場合は1を返し、失敗した場合は0を返します。
  • シェルは終了状態をゼロとみなして成功を示し、ゼロでない場合は失敗を示します。
  • ==だから私たちは演算子の戻りコードを無効にします。

私のコードが表示されるレコードを考慮していないことに気づきました。後ろに予告編があると、ファイルが無効になることがあります。試してみてください。

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

関連情報