列数据类型验证

列数据类型验证

我试图使用 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以跳过输入文件的第一行(标题行)
  • 如果您想匹配不匹配的电子邮件地址,请否定正则表达式匹配:!~
  • 双括号[[...]]测试不是有效的sh构造,已更改为[...]与测试运算符结合使用-n,如果后面的字符串非空,则为 true。

我还添加$val到输出中,echo以便能够查看错误发生的位置并打印$n而不是$1.根据需要将其改回。输出转到 stderr ( >&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

如果您将整个字段与 和 匹配,则您的正则表达式与电子邮件地址不匹配^$例如使用可以工作
。确保至少引用正则表达式参数以防止可能的 shell 解释。'[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,然后让 shell 将 STDERR 重定向到日志文件2>(您awk如果需要,可以直接写入错误日志文件,但使用 shell 重定向 STDERR 更灵活)。

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

您还可以让它在 STDOUT 上返回错误计数,以便为$valshell 变量捕获:

#!/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,awk则将使用-FILENAME,因此错误日志将类似于:

-:4:3|file3.txt|xyz

相关内容