列データ型の検証

列データ型の検証

特定の列が正規表現と一致しないことを確認するためにawkコマンドを使用しようとしています。 (基本的に私は一様な形式のファイルの列をチェックしていますが、そうでなければエラーが発生するはずです。)

format=$2
col_pos=$1

val= `awk -F "|’’ -v m="$format" -v n="$col_pos" '$n ~ "^"m"$"{print $1}' sample_file.txt`

if [[ $val != "" ]]; then
   echo " column value is having unexpected format"
fi

sh sample.sh  [a-z]{8}@gmail.com 3

awkコマンドでエラーが発生します。誰でもこの問題を解決するのに役立ちますか?

入力ファイル:

fileid|filename|contactemail
1|file1.txt|[email protected]
2|file2.txt|[email protected]
3|file3.txt|xyz  -------->invalid column value as it doesnt satisfies the format @gmail.com 

以下はサンプルプログラムの実行です(xyzが有効な電子メールではないため、エラーが発生すると予想されます)。

$ sh sample.sh 3 [a-z]@gmail.com
$ sh -x sample.sh 3 [a-z]@gmail.com
+ format='[a-z]@gmail.com'
+ col_pos=3
++ awk -F '~' -v 'm=[a-z]@gmail.com' -v n=3 '$n ~ "^"m"$"{print $1}' sample_file.txt
+ val=
+ [[ '' != '' ]]

答え1

これにはいくつかの問題があります。

  • #!/bin/shスクリプトにshebangを追加しました。chmod +x sample.sh以下を使用して実行可能にする場合./sample.sh ...
  • フィールド区切り文字を次のように変更します。'|'
  • 廃止されたコマンドの置換バックティック記号を変数割り当ての空白文字`...`に置き換えます。$(...)
  • NR>1入力ファイルの最初の行(ヘッダー行)をスキップするように追加します。
  • 一致しないメールアドレスを一致させるには、正規表現の一致を無効にしてください。!~
  • 二重括弧[[...]]テストは有効な設定ではなく、次の文字列が空でない場合はtrueを返すテスト演算子で使用するようにsh変更されました。[...]-n

また、エラーが発生した場所を確認し、必要に応じて再印刷できるように出力に$val追加しました。出力はstderr()に移動し、スクリプトは失敗を示すためにゼロ以外の終了状態で終了します。echo$n$1>&2

修正されたスクリプト:

#!/bin/sh

val=$( awk -F'|' -v n="$1" -v m="$2" 'NR>1 && $n !~ "^" m "$"{ print $n }' sample_file.txt )

if [ -n "$val" ]; then
    echo "column value is having unexpected format: $val" >&2
    exit 1
fi

たとえば、を使用してフィールド全体をに^一致させると、正規表現は電子メールアドレスと一致しません。可能なシェル解釈を避けるために、少なくとも正規表現引数を引用します。$
'[a-z][email protected]'

実行例:

$ ./sample.sh 3 '[a-z][email protected]'
column value is having unexpected format: xyz
$ ./sample.sh 3 'xyz'
column value is having unexpected format: [email protected]
[email protected]

答え2

@Freddyの優れた答えに基づいて、awk入力ファイルで見つかったエラーをSTDERRに書き込んだ後、シェルにSTDERRをログファイルにリダイレクトさせることができます2>できるawk必要に応じてエラーログファイルに直接書き込むことができますが、シェルを使用してSTDERRをリダイレクトする方が柔軟です。

awk -F'|' -v n="$1" -v m="$2" '
    FNR>1 && $n !~ "^" m "$" {
      print NR ":" $0 > "/dev/stderr"
    }' input.txt 2> error.log

$valシェル変数をキャプチャするためにSTDOUTにエラー数を返すこともできます。

#!/bin/sh

val=$(awk -F'|' -v n="$1" -v m="$2" '
        FNR>1 && $n !~ "^" m "$" {
          printf "%s:%s:%s\n", FILENAME, FNR, $0 > "/dev/stderr"
          count++
        }
        END {print count}' sample_file.txt 2> errors.log
     )

if [ "$val" != 0 ]; then
    echo "$val errors found in input:"
    cat errors.log
    exit 1
fi

たとえば、

$ ./sample.sh 3 xyz
2 errors found in input:
sample_file.txt:2:1|file1.txt|[email protected]
sample_file.txt:3:2|file2.txt|[email protected]

注:入力がSTDINから来る場合はFILENAMEがawk使用されるため、-エラーログは次のようになります。

-:4:3|file3.txt|xyz

関連情報