- 论坛徽章:
- 1
|
19.10 执行shell函数
要执行函数,简单地键入函数名即可。这里是带有一个参数的f i n d i t函数,参数是某个系
统文件。
$ findit groups
19.10.1 删除shell函数
现在对函数做一些改动。首先删除函数,使其对s h e l l不可利用。使用u n s e t命令完成此功
能。删除函数时u n s e t命令格式为:
unset function_name
$ unset findit
如果现在键入s e t命令,函数将不再显示。
19.10.2 编辑shell函数
编辑函数f u n c t i o n s . m a i n,加入f o r循环以便脚本可以从命令行中读取多个参数。改动后函
数脚本如下:- #!/bin/sh
- # functions.main.sh
- #
- # findit: this is front end for the basic find command
- findit() {
- # findit
- if [ $# -lt 1 ]; then
- echo "usage :findit file"
- return 1
- fi
- for loop
- do
- find / -name $loop -print
- done
- }
复制代码 再次定位函数
$. /functions.main.sh
使用s e t命令查看其是否被载入,可以发现s h e l l正确解释f o r循环以接受所有输入参数。- #!/bin/sh
- # functions.main.sh
- #
- # findit: this is front end for the basic find command
- findit() {
- # findit
- if [ $# -lt 1 ]; then
- echo "usage :findit file"
- return 1
- fi
- for loop "$@"
- do
- find / -name $loop -print
- done
- }
复制代码 现在执行改动过的f i n d i t函数,输入两个参数:
$ findit LPSO.doc passwd
对应在Linux的默认bash中,我们应该在脚本的某处使用函数名字调用它,而不是是否看它载入。
19.10.3 函数举例
既然已经学习了函数的基本用法,现在就用它来做一些工作。函数可以节省大量的编程
时间,因为它是可重用的。
1. 变量输入
以下脚本询问名,然后是姓。
echo -n "What is your first name :"
read F_NAME
echo -n "What is your surname :"
read $S_NAME
要求输入字符必须只包含字母。如果不用函数实现这一点,要写大量脚本。使用函数可
以将重复脚本删去。这里用a w k语言测试字符。以下是取得只有小写或大写字符的测试函数。- char_name()
- # char_name
- # to call: char_name string
- # check if $1 does indeed contain only characters a-z,A-Z
- {
- # assign the argument across to new variable
- _LETTERS_ONLY=$1
- _LETTERS_ONLY=`echo $1 | awk '{if($0~/[^a-zA-Z]/) print "1"}'`
- if [ "$_LETTERS_ONLY" != "" ]
- then
- # oops errors
- return 1
- else
- # contains only chars
- return 0
- fi
- }
复制代码 首先设置变量$ 1为一有意义的名字,然后用a w k测试整个传送记录只包含字母,此命令输
出(1为非字母,空为成功)保存在变量_ L E T T E R S O N LY中。
然后执行变量测试,如果为空,则为成功,如果有值,则为错误。基于此项测试,返回
码然后被执行。在对脚本的函数调用部分进行测试时,使用返回值会使脚本清晰易懂。
使用i f语句格式测试函数功能:- if char_name $F_NAME
- then
- # all ok breakout
- break
- else
- name_error $FNAME
- fi
复制代码 如果有错误,可编写一个函数将错误反馈到屏幕上。- name_error()
- # display an error message
- {
- echo " $@ contains errors, it must contain only letters"
- }
复制代码 函数n a m e e r r o r用于显示所有无效输入错误。使用特殊变量$ @显示所有参数,这里为变
量F N A M E和S N A M E值。完成脚本如下:- #!/bin/sh
- # func2.sh
- char_name()
- # char_name
- # to call: char_name string
- # check if $1 does indeed contain only characters a-z,A-Z
- {
- # assign the argument across to new variable
- _LETTERS_ONLY=$1
- _LETTERS_ONLY=`echo $1 | awk '{if($0~/[^a-zA-Z]/) print "1"}'`
- if [ "$_LETTERS_ONLY" != "" ]
- then
- # oops errors
- return 1
- else
- # contains only chars
- return 0
- fi
- }
- name_error()
- # display an error message
- {
- echo " $@ contains errors, it must contain only letters"
- }
- while :
- do
- echo -n "What is your first name :"
- read F_NAME
- if char_name $F_NAME
- then
- # all ok breakout
- break
- else
- name_error $FNAME
- fi
- done
- while :
- do
- echo -n "What is your surname :"
- read S_NAME
- if char_name $S_NAME
- then
- # all ok breakout
- break
- else
- name_error $S_NAME
- fi
- done
复制代码 注意每个输入的w h i l e循环,这将确保不断提示输入直至为正确值,然后跳出循环。当然,
实际脚本拥有允许用户退出循环的选项,可使用适当的游标,正像控制0长度域一样。
运行上述脚本的情况如下:- What is your first name :Davi3d
- contains errors, it must contain only letters
- What is your first name :David
- What is your surname :Tansley1
- Tansley1 contains errors, it must contain only letters
- What is your surname :Tansley
复制代码 2. echo问题
e c h o语句的使用类型依赖于使用的系统是L I N U X、B S D还是系统V,本书对此进行了讲解。
下面创建一个函数决定使用哪种e c h o语句。
使用e c h o时,提示应放在语句末尾,以等待从r e a d命令中接受进一步输入。
L I N U X和B S D为此使用e c h o命令- n选项。
以下是L I N U X(B S D)e c h o语句实例,这里提示放于e c h o后面:
$ echo -n "Your name :"
Your name :{{?}}
系统V使用\ C保证在末尾提示:
echo "Your name :\C"
Your name :♢
在e c h o语句开头L I N U X使用- e选项反馈控制字符。其他系统使用反斜线保证s h e l l获知控
制字符的存在。
有两种方法测试e c h o语句类型,下面讲述这两种方法,这样,就可以选择使用其中一个。
第一种方法是在e c h o语句里包含测试控制字符。如果键入\ 0 0 7和一个警铃,表明为系统V,
如果只键入\ 0 0 7,显示为L I N U X。
以下为第一个控制字符测试函数。- uni_prompt()
- {
- if [ `echo "\007"` == "\007" ] >/dev/null 2>&1
- # does a bell sound or are the characters just echoed??
- then
- # characters echoed, it's LINUX/BSD
- echo -e -n "$@"
- else
- # it's System V
- echo "$@\c"
- fi
- }
复制代码 注意这里又用到了特殊变量$ @以反馈字符串,要在脚本中调用上述函数,可以使用:
uni_prompt "\007 there goes the bell ,What is your name:"
这将发出警报并反馈‘ What is your name:’,并在行尾显示字符串。如果在末尾出现字
符,则为系统V版本,否则为L I N U X / B S D版本。
第二种方法使用系统V \c测试字母z是否悬于行尾。- uni_prompt()
- # uni_prompt
- # univeral prompt
- {
- if [ `echo "Z\c"` == "Z" ] >/dev/null 2>&1
- # echo any character out, does it hang on to the end of line ??
- then
- # yes, it's System V
- echo "$@\c"
- else
- # No, it's LINUX, BSD
- echo -e -n "$@"
- fi
- }
复制代码 要在脚本中调用上述函数,可以使用:
uni_prompts "\007 there goes the ,What is your name:"
使用两个函数中任意一个,并加入一小段脚本:
uni_prompt "\007 There goes the bell, What is your name :"
read NAME
将产生下列输出:
There goes the be,What is your name:
3. 读单个字符
在菜单中进行选择时,最麻烦的工作是必须在选择后键入回车键,或显示“ press any key
to continue”。可以使用d d命令解决不键入回车符以发送击键序列的问题。
d d命令常用于对磁带或一般的磁带解压任务中出现的数据问题提出质疑或转换,但也可
用于创建定长文件。下面创建长度为1兆的文件m y f i l e。
dd if:/dev/zero of=myfile count=512 bs=2048
d d命令可以翻译键盘输入,可被用来接受多个字符。这里如果只要一个字符, d d命令需
要删除换行字符,这与用户点击回车键相对应。d d只送回车前一个字符。在输入前必须使用
s t t y命令将终端设置成未加工模式,并在d d执行前保存设置,在d d完成后恢复终端设置。
函数如下:- read_a_char()
- # read_a_char
- {
- # save the settings
- SAVEDSTTY=`stty -g`
- # set terminal raw please
- stty cbreak
- # read and output only one character
- dd if=/dev/tty bs=1 count=1 2> /dev/null
- # retore terminal and restore stty
- stty -cbreak
- stty $SAVEDSTTY
- }
复制代码 要调用函数,返回键入字符,可以使用命令替换操作,例子如下:- echo -n "Hit Any Key To Continue"
- character=`read_a_char`
- echo " In case you are wondering you pressed $character"
复制代码 |
|