加入收藏 | 设为首页 | 会员中心 | 我要投稿 阜阳站长网 (https://www.0558zz.com/)- 科技、建站、内容创作、云计算、网络安全!
当前位置: 首页 > 综合聚焦 > Linux > 正文

LINUX学习:shell的编程结构体(函数、条件结构、循环结构)

发布时间:2020-07-24 09:47:56 所属栏目:Linux 来源:互联网
导读:介绍《LINUX学习:shell的编程结构体(函数、条件结构、循环结构)》开发教程,希望对您有用。

《LINUX学习:shell的编程结构体(函数、条件结构、循环结构)》要点:
本文介绍了LINUX学习:shell的编程结构体(函数、条件结构、循环结构),希望对您有用。如果有疑问,可以联系我们。

本文目次:

1.1 shell函数

1.2 条件布局:if

1.3 条件布局:case

1.4 条件布局:select

1.5 循环布局:for

1.6 循环布局:while

1.7 循环布局:until

1.8 exit、break、continue和return


1.1 shell函数

在shell中,函数可以被当作命令一样执行,它是命令的组合布局体.可以将函数看成是一个普通命令或者一个小型脚本.

起首给出几个关于函数的结论:

(1).当在bash中直接挪用函数时,如果函数名和命令名相同,则优先执行函数,除非使用command命令.例如:定义了一个名为rm的函数,在bash中输入rm执行时,执行的是rm函数,而非/bin/rm命令,除非使用"command rm ARGS".

(2).当前shell定义的函数只能在当前shell使用,子shell无法承继父shell的函数定义.除非使用"export -f"将函数导出为全局函数.

(2).界说了函数后,可以使用unset -f移除当前shell中已界说的函数.

(3).除非出现语法错误,或者已经存在一个同名只读函数,不然函数的退出状态码是函数内部结构中最后执行的一个命令的退出状态码.

(4).可以使用typeset -f [func_name]或declare -f [func_name]查看当前shell已界说的函数名和对应的界说语句.使用typeset -F或declare -F则只显示当前shell中已界说的函数名.

(5).函数可以递归,递归条理可以无限.

函数的语法布局:

[ function ] name () compound-cmd [redirection]

上面的语法结构中定义了一个名为name的函数,关键字function是可选的,如果使用了function关键字,则name后的括号可以省略.compound-cmd是函数体,通常使用大括号{}包抄,由于历史原因,大括号本身也是关键字,所以为了不产生歧义,函数体必须和大括号使用空格、制表符、换行符分隔开来.还可以指定可选的函数重定向功能,这样当函数被调用的时候,指定的重定向也会被执行.

例如:界说一个名为rm的函数,该函数会将传递的所有文件移动到"~/backup"目录下,目的是替代rm命令,避免误删除的危险操作.

[root@linuxidc ~]# function rm () { [ -d ~/rmbackup ] || mkdir ~/rmbackup;/bin/mv -f $@ ~/rmbackup; } &>/dev/null

在挪用rm函数时,只需是给rm函数传递参数即可.例如,要删除/tmp/a.log.

[root@linuxidc ~]# rm /tmp/a.log

在执行函数时,会将执行可能输出的信息重定向到/dev/null中.

为了让函数在子shell(例如脚本)中也可以使用,使用export的"-f"选项将其导出为全局函数.撤消函数的导出则使用export的"-n"选项.

export -f rm
export -n rm

关于shell函数,还有几个必要说明的知识点:

(6).shell函数也接受位置变量$0、$1、$2...,但函数的位置参数是调用函数时传递给函数的,而非传递给脚本的参数.所以脚本的位置变量和函数的位置变量是不同的,但是$0和脚本的位置变量$0是一致的.另外,函数也接受特殊变量"$#",和脚本的"$#"一样,它也表现位置变量的个数.

(7).函数体内部可以使用return命令,当函数结构体中执行到return命令时将退出整个函数.return后可以带一个状态码整数,即return n,表现函数的退出状态码,不给定状态码时默认状态码为0.

(8).函数结构体中可以使用local命令定义本地变量,例如:local i=3.本地变量只在函数内部(包含子函数)可见,函数外不可见.

1.2 条件布局:if

语法布局:

if test-commands1; then

commands1;

[elif test-commands2; then

commands2;]

...

[else

commands3;]

fi

if的判断很简单,一切都以返回状态码是否为0为判决条件.如果test-commands1执行后的退出状态码为0(不是其执行结果为0),则执行commands1部分的结构体,不然如果test-commands2返回0则执行commands2部分的结构体,如果都不满足,则执行commands3的结构体.

常见的test-commands有几种类型:

(1).一条普通的敕令.只要该敕令退出状态码为0,则执行then后的语句体.例如:

if echo haha &>/dev/null;then echo go;fi

(2).测试语句.例如test、[]、[[]].

(3).使用逻辑运算符,包含!、&&和||.该特性主要是为普通命令而提供,因为测试语句自身就支持逻辑运算.所以,对于测试语句就提供了两种写法,一种是将逻辑运算符作为测试语句的一部分,一种是将逻辑运算符作为if语句的一部分.例如:

if ! id "$name" &>/dev/null;then echo "$name" miss;fi
if ! [ 3 -eq 3 ];then echo go;fi
if [ ! 3 -eq 3 ];then echo go;fi
if [ 3 -eq 3 ] && [ 4 -eq 4 ] ;then echo go;fi
if [ 3 -eq 3 -a 4 -eq 4 ];then echo go;fi
if [[ 3 -eq 3 && 4 -eq 4 ]];then echo go;fi

注意,在if语句中使用()不能改变优先级,而是让括号内的语句成为命令列表并进入子shell运行.因此,要改变优先级时,必要在测试语句中完成.

1.3 条件布局:case

语法布局:

case word in

[ [(] pattern [| pattern]…)

command-list ;;]

esac

sysV作风的服务启动脚本是shell脚本中使用case语句最典型案例.例如:

case "$1" in
    start)
        start;;
    stop)
        stop;;
    restart)
        restart;;
    reload | force-reload)
        reload;;
    status)
        status;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|reload|force-reload}"
        exit 2
esac

从上面的示例中,可以看出一些结论:

(1).case中的每个小分句都以双分号";;"结尾,但最后一个小分句的双分号可以省略.实际上,小分句除了使用";;"结尾,还可以使用";&"和";;&"结尾,只不外意义不同,它们用的不多,不外为了文章完整性,稍后还是给出说明.

(2).每个小分句中的pattern部分都使用括号"()"包抄,只不过左括号"("不是必须的.

(3).每个小分句的pattern支持通配符模式匹配(不是正则匹配模式,因此只有3种通配元字符:"*"、"?"和[...]),其中使用"|"分隔多个通配符pattern,表现满足其中一个pattern即可.例如"([yY] | [yY][eE][sS]])"表现即可以输入单个字母的y或Y,还可以输入yes三个字母的任意大小写格式.

set -- y;case "$1" in ([yY]|[yY][eE][sS]) echo right;;(*) echo wrong;;esac

其中"set -- string_list"的作用是将输入的string_list依照IFS分隔后分别赋值给位置变量$1、$2、$3...,因此此处是为$1赋值字符"y".

(4).最后一个小分句使用的pattern是"*",表示无法匹配前面所有小分句时,将匹配该小分句.一般最后一个小分句都会使用"*"避免case语句无法匹配的情况,在shell脚本中,此小分句一般用于提示用户脚本的使用办法,即给出脚本的Usage.

(5).附加一个结论:如果任何模式都不匹配,该命令的返回状态是零;不然,返回最后一个被执行的命令的返回值.

如果小分句不是使用双分号";;"结尾,而是使用";&"或";;&"结尾,则case语句的行为将转变.

◇ ";;"结尾符号表现小分句执行完成后立即退出case语句.

◇ ";&"表现继续执行下一个小分句中的command部分,而无需进行匹配动作,并由此小分句的结尾符号来决定是否继续操作下一个小分句.

◇ ";;&"表现继续向后(不止是下一个,而是一直向后)匹配小分句,如果匹配成功,则执行对应小分句中的command部分,并由此小分句的结尾符号来决定是否继续向后匹配.

示例如下:

set -- y
case "$1" in
    ([yY]|[yY][eE][sS])
        echo yes;&
    ([nN]|[nN][oO])
        echo no;;
    (*)
        echo wrong;;
esac
yes
no

在此示例中,$1能匹配第一个小分句,但第一个小分句的结尾符号为";&",所以无需判断地直接执行第二个小分句的"echo no",但第二个小分句的结尾符号为";;",于是直接退出case语句.因此,即使$1无法匹配第二个小分句,case语句的成果中也输出了"yes"和"no".

set -- y
case "$1" in
    ([yY]|[yY][eE][sS])
        echo yes;;&
    ([nN]|[nN][oO])
        echo no;;
    (*)
        echo wrong;;
esac
yes
wrong

在此示例中,但第一个小分句的结尾符号为";;&",所以继续向下匹配,第二个小分句未匹配胜利,直到第三个小分句才被匹配上,于是执行第三个小分句中的"echo wrong",但第三个小分句的结尾符号为";;",于是直接退出case语句.所以,结果中输出了"yes"和"wrong".

1.4 条件布局:select

shell中提供菜单选择的条件判断布局.例如:

[root@linuxidc ~]# select fname in cat dog sheep mouse;do echo your choice: "$REPLY) $fname";break;done
1) cat
2) dog
3) sheep
4) mouse
#? 3                      # 在此选择序号3
your choice: "3) sheep"   # 将输出序号3对应的内容

语法布局:

select name [ in word ] ; do cmd_list ; done

它的布局几乎和for循环的布局相同.有以下几个要点:

(1).in关键词后的word将根据IFS变量进行分割,分割后的每一项都进行编号,作为菜单序号被输出,如果省略in word,则等价于"in $@",即将地位变量的内容作为菜单项.

(2).当选择菜单序号后,该序号的内容将保留到变量name中,并且所输入的内容(一般是序号值,例如上面的例子中输入的3,但不规定一定要输入序号值,例如随便输入几个字符)保留保留到特殊变量REPLY中.

(3).每次输入选择后,select语句都将重置,如果输入的菜单序号存在,则cmd_list会重新执行,变量name也将重置.如果没有break敕令,则select语句会一直运行,如果遇到break敕令,将退出select语句.

仍旧是上面的示例:但不是用break

[root@linuxidc ~]# select fname in cat dog sheep mouse;do echo your choice: "$REPLY) $fname";done  
1) cat
2) dog
3) sheep
4) mouse
#? 2
your choice: "2) dog"
#? habagou                    # 随意输入几个字符
your choice: "habagou) "      # 变量fname被重置为空,变量REPLY被赋予了输入的值habagou
#? 2 3
your choice: "2 3) "   
#? ^C                         # 直到杀失落进程select才结束

(编辑:阜阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读