22,判断用户输入的有效性
时间:2004-12-27 来源:wingger
创建屏幕输入
屏幕输入或数据输入是接受输入(这里指键盘)并验证其有效的能力。如果有效,接受它,如果无效,放弃该输入。
前面讲到了基于一些条件的测试函数,例如字符串长度、字符串是数字或字符型,这一章在脚本中将继续使用这些函数。
本章内容有:
• 验证有效输入。
• 增加、删除、修改和查看记录。
• 修改脚本的工作文件。
本章开始读起来可能有些累人,因此可以先大概看一下,再慢慢细看。验证有效性的代码量很大,这是因为为捕获所有错误,脚本必须测试几乎所有可能的错误。
现在在创建一个一般文件以修改系统地过程中逐步实现每一个任务:增加、删除、修改和查看记录。这里也将创建一个个人文件以修改系统。记录文件D B F I L E保存下列信息:
和查看记录。这里也将创建一个个人文件以修改系统。记录文件D B F I L E保存下列信息:
域长度允许输入描述
职员号码1 0 数字雇员代码
名2 0 字符雇员名
姓2 0 字符雇员姓
部门- 记帐雇员所在部门
IT
服务
销售
权利
域间用冒号:分隔,例如:
:::
每一个任务即是一个完整脚本。脚本中一小部分复制于前面的两个例子。这样做是因为本章主要用于显示怎样用文件修改系统。刚开始编写脚本时,最令人头疼的事就是将修改的
文件或数据库系统放在一起后的文档清理工作。
运行脚本应具有一些菜单选项,与任务或模块相连接或包含在文件里与菜单脚本相关的一系列函数相连接。每一段脚本均执行t r a p命令,信号2、3和1 5被忽略。
1 增加记录
将记录加入文件,包含以下两个步骤:
1) 确认输入有效。
2) 将记录写入文件。
第一个任务就是将一些函数放在一起,这些函数测试域是字符型或数字型及域的长度限制,即数据输入有效性检验。有效性检验将用于增加数据和修改数据。幸运的是前面已经编好这些函数,检测字符串及长度的函数脚本如下:
length_check()
{
_STR=$1
_MAX=#2
_LENGTH=`echo $_STR|awk '{print length($0)}'`
if [ "$_LENGTH" -gt "$_MAX" ];then
return 1
else
return 0
fi
}
检测字符串是否为数字型,函数脚本如下:
a_number()
{
_NUM=$1
_NUM=`echo $1|awk '{if($0~/[^0-9]/) print "1"}'`
if [ "$_NUM" != "" ]
then
return 1
else
return 0
fi
}
检测字符串是否为字符型,函数脚本如下:
characters()
{
_LETTERS_ONLY=$1
_LETTERS_ONLY=`echo $1|awk '{if($0~/[^a-zA-Z]/) print "1"}'`
if [ "$_LETTERS_ONLY" != "" ]
then
return 1
else
return 0
fi
当域读取完毕时,调用相应函数,测试其返回值。
这里也需要提示以保存屏幕信息直到键入某键删除这些信息,下列函数用到了r e a d _ a _ c h a r函数。
continue_proptYN()
{
echo -n "Hit any key to continue.."
DUMMY=`read_a_char`
}
当用户输入雇员代码后,要确保编号还没有用到,此域必须唯一。测试这一点有几种方法,这里使用g r e p。g r e p搜寻字符串_ C O D E中的雇员编号,如果a w k返回空值,则不存在匹配编号,函数返回状态码0。函数如下(这里在g r e p中使用“ $ _ C O D E >”抽取相应匹配,变量用双引号括起来,如果用单引号,则返回空值):
check_duplicate()
{
_CODE=$1
MATCH=`grep "$_CODE>" $DBFILE`
echo $_CODE
if [ "$MATCH" = "" ];then
return 0
else
return 1
fi
}
以下是检测雇员编号代码段,之后继续讲解其功能。
while:
do
echo -n "Employee Staff Number :"
read NUM
if [ "$NUM" != "" ];then
if a_number $NUM;then
NUM_PASS=0
else
NUM_PASS=1
fi
if length_check $NUM 10;then
LEN_PASS=0
else
LEN_PASS=1
fi
if check_duplicate $NUM;then
DUPLICATE=0
else
DUPLICATE=1
echo "Staff Number: There is already an employee with this number"
continue_prompt
fi
if [ "$LEN_PASS" ="0" -a "$NUM_PASS" ="0" -a "$DUPLICATE" = "0" ]
then
break
else
echo "Staff Number: Non-Numeric or Too Many Numbers In Field"
continue_prompt
fi
else
echo "Staff Number:no Input Detected,this field requires a number"
continue_prompt
fi
done
所有检测语句均在w h i l e循环中(实际上每一个数据输入域均在一单独的w h i l e循环中),如果没有有效数据,提示返回初始读位置。
读完雇员编号,继续检测域中数据是否存在:
if ["$NUM"!=""]
如果域中没有输入数据。则不执行i f语句t h e n部分。e l s e部分在脚本结尾部分,用于显示下列信息:
Staff Number:No Input Detected ,This Field Requires a Number
t h e n部分包括对域输入数据的所有有效性检测。假定存在输入,调用a _ n u m b e r函数,测试传输字符串是否为一数字,如果是,函数返回0,如果不是,函数返回1。基于此返回值,设置指针NU M_ PA S S为0,表示返回值正确(数字型),设置为1,表示返回失败(非数字型)。
然后调用函数l e n g t h _ c h e c k,参数为字符串及字符串包含字符最大数目。这里为1 0,如果字符串长度小于1 0,则返回0,否则返回1。指针L E N _ PA S S设置为0,表示返回成功(长度不超过最大长度),设置为1,表示返回失败(长度超出最大长度)。
接下来检测是否有重复雇员编号。调用函数c h e c k _ d u p l i c a t e,如果没有发现重复编号,设置指针D U P L I C AT E为0,最后测试三个指针变量均为0(无错误),为此使用A N D测试,如果条件同时成立,执行t h e n部分语句。
如果测试通过,则存在有效域。这时处在w h i l e循环中,因此需要用b r e a k命令跳出循环。
如果有效性测试任何一部分失败,即长度测试或类型测试之一不通过,返回错误信息并显示在屏幕底部。
Staff Number : Non_Numeric or Too Many Numbers In Field 。
验证第2和第3域有效性,处理过程一样。有效性验证这次在另一个循环中。这次调用c h a r a c t e r s函数,检验域是否只包含字符。下述脚本做名字有效性检验:
while:
do
echo -n "Employee First Number :"
read F_NAME
if [ "$F_NAME" != "" ];then
if characters $F_NUM;then
F_NAME_PASS=0
else
F_NAME_PASS=1
fi
if length_check $NUM 20;then
LEN_PASS=0
else
LEN_PASS=1
fi
if [ "$LEN_PASS" ="0" -a "$F_NAME_PASS" = "0" ];then
break
else
echo "Staff Number: Non-character of too many characters In Field"
continue_prompt
fi
else
echo "Staff First Number:no Input Detected,this field requires a number"
continue_prompt
fi
done
使用c a s e语句检验部门域(列表见下面),因为公司只包含5个部门,部门域必须是其中之一。注意对每个部门有三个不同的匹配模式,可以由用户键入部门名称加以验证。如果找到
匹配模式,用户跳出c a s e语句,并显示有效部门列表。
while:
do
echo -n "company department :"
read DEPART
case #DEPART in
ACCOUNTS|Accounts|accounts)break;;
SALES|Sales|sales)break;;
IT|It|it)break;;
CLAIMS|Claims|claims)break;;
SERVICES|Services|services)break;;
*)echo "Department: Accounts,Sales,IT,Claims,Services";;
esac
done
当所有域的有效性验证完成后,将提示用户是否保存此记录,这里使用函数c o n t i n u e _ p r o m p t Y N,前面讲过这个函数,它处理Y或N响应,用户也可以点击回车键表示缺
省回答。
如果用户选择N,进入i f语句代码段并退出脚本。如果用户输入许多记录,然后在w h i l e循环中调用函数以增加记录,这种方法将不会返回菜单或增加记录后退出。
如果用户选择Y,保存记录。将记录加入一个文件的脚本是:
echo "$NUM:$F_NAME:$S_NAME:$DEPART">>$DBFILE 。
然后显示信息通知用户记录已存入文件。s l e e p命令将脚本进程挂起1 s,以使用户有足够的时间查看该信息。
域分隔符是冒号,文件以姓域分类,输出存入一临时工作文件,然后文件移入初始文件D B F I L E。文件转移操作时,会测试其最后状态,如果存在问题,则通知用户该信息。