我试图使用 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 上返回错误计数,以便为$val
shell 变量捕获:
#!/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