shell编程 - shell函数

        随着功能丰富,脚本变得越来越庞大和复杂,如何把复杂的任务分解成小的、具体的任务?

先拆分主要步骤,再逐个步骤进行细化实现,自顶向下设计。shell编程尤其适用自顶向下设计。

shell函数

        继续之前的系统信息报告生成器脚本,新增需求:需要展示系统的运行时间、磁盘空间、用户空间。

假设每个需求对应一条命令,我们可以用命令替换的方式应用实现。

#!/bin/bash

# a program to output system information report

TITLE="System Information Report For $HOSTNAME"

CURRENT_TIME=$(date +"%x %r %Z")

TIME_STAMP="Generated $CURRENT_TIME ,by $USER"

echo << _EOF_
<html>
<head>
<title>$TITLE</title>
</head>
<body>
<h1>$TITLE</h1>
<p>$TIME_STAMP</p>
$(report_uptime)
$(report_disk_space)
$(report_home_space)
</body>
</html>
_EOF_

        对于以上$(report_uptime) $(report_disk_space) $(report_home_space)三个命令,如何组织实现?主要有两种方式

        编写三个独立的脚本,把脚本文件放到环境变量PATH所列的目录中。或者,可以将脚本作为shell函数嵌入到程序中。

        shell函数有两种语法形式,第一种,

function name{
    commands
    return
}

其中,name是指这个函数的名称,commands是指这个函数中的一系列命令。

第二种形式,

name(){
    commands
    return
}

shell函数使用演示脚本

#!/bin/bash

# shell function demo

function funct {
    echo "Step 2"
    return
}

# Main program starts here

echo "Step 1"
funct
echo "Step 3"

shell脚本中,shell函数的定义在脚本中的位置必须在它被调用的前面

函数的调用直接使用函数名称即可,不需要加括号

#!/bin/bash

# Program to output a system information page

TITLE="Syatem Information Report For $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIME_STAMPT="Generated $CURRENT_TIME,by $USER"

report_uptime () {
    return
}

report_disk_space () {
    return
}

report_home_space () {
    return
}

cat <<- _EOF_
<html>
    <head>
        <title>$TITLE</title>
    </head>
    <body>
        <h1>$TITLE</h1>
        <p>$TIME_STAMPT</p>
        $(report_uptime)
        $(report_disk_space)
        $(report_home_space)
    </body>
</html>
_EOF_

shell函数命名规则和变量相同。

一个函数中必须至少包含有一条命令。return命令(可选的)可以满足该要求

局部变量

        在shell函数中,经常需要使用局部变量。局部变量仅仅在定义它们的shell函数中有效,一旦shell函数终止,它们就不再存在。

        为什么引入局部变量的概念呢?我总结了一下,主要包含且不限以下两点:

1、局部变量可以让程序员使用已存在的变量名称,无论是脚本中的全局变量还是其他shell函数中的变量,不用担心变量命名冲突的问题

2、shell函数中尽量使用局部变量,可以保证shell函数相互独立,也独立于它们所在的脚本,增加shell函数的可移植性。因为减少了外部变量的使用,移植到新的脚本上下文中,不用担心shell函数的能否运行起来。(保持shell函数的独立性非常有用 - 能够直接从一个脚本中复制剪切shell函数到另一个脚本中使用运行

#!/bin/bash

# local-variable:script to demostrate local variables

foo=0 # global variable foo

funct_1 () {
    local foo # variable foo local to funct_1
    foo=1
    echo "funct_1: foo=$foo"
}
funct_2 () {
    local foo # variable foo local to funct_2
    foo=2
    echo "funct_2: foo=$foo"
}

echo "global: foo=$foo"
funct_1
echo "global: foo=$foo"
funct_2
echo "global: foo=$foo"

局部变量是通过在变量名前面添加 local 来定义的。

程序编写中的一些小技巧

        在程序设计中,我们需要保持编写的程序能够持续有效运行。在之前的系统信息报告生成器脚本中,定义的report_uptime、report_disk_space、report_home_space方法中没有具体的业务逻辑流程,相当于一个空函数。一般将这种类型的代码称为stub代码,即起到一个占位的作用。

        在编写stub时,最好能够包含一些能够为程序员提供反馈信息的东西,以便程序员进行调试。

#!/bin/bash

# Program to output a system information page

TITLE="Syatem Information Report For $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIME_STAMPT="Generated $CURRENT_TIME,by $USER"

report_uptime () {
    echo "Function report_uptime executed."  # 一些反馈的信息
    return
}

report_disk_space () {
    echo "Function report_disk_space executed." # 一些反馈的信息
    return
}

report_home_space () {
    echo "Function report_home_space executed." # 一些反馈的信息
    return
}

cat <<- _EOF_
<html>
    <head>
        <title>$TITLE</title>
    </head>
    <body>
        <h1>$TITLE</h1>
        <p>$TIME_STAMPT</p>
        $(report_uptime)
        $(report_disk_space)
        $(report_home_space)
    </body>
</html>
_EOF_

        如果成功输出以上函数中设置的反馈信息,我们可以确定,函数的编写定义和使用没有问题。可以对各个函数进行业务逻辑流程的编写了。

#!/bin/bash

# Program to output a system information page

TITLE="Syatem Information Report For $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIME_STAMPT="Generated $CURRENT_TIME,by $USER"

report_uptime () {
    cat <<- _EOF_
        <h2>System Uptime</h2>
        <pre>$(uptime)</pre>
    _EOF_
    return
}

report_disk_space () {
    cat <<- _EOF_
        <h2>Disk Space Utilization</h2>
        <pre>$(df -h)</pre>
    _EOF_
    return
}

report_home_space () {
    cat <<- _EOF_
        <h2>Home Space Utilization</h2>
        <pre>$(du -sh /home/*)</pre>
    _EOF_
    return
}

cat <<- _EOF_
<html>
    <head>
        <title>$TITLE</title>
    </head>
    <body>
        <h1>$TITLE</h1>
        <p>$TIME_STAMPT</p>
        $(report_uptime)
        $(report_disk_space)
        $(report_home_space)
    </body>
</html>
_EOF_

以上内容都属于自顶向下设计的思想过程。

        编写的report_home_space函数在有些系统只有超级用户才能运行。一个更好的解决方案是根据执行脚本的用户权限来调整脚本的行为。在下一节中讨论该问题。

!!! 在.bashrc文件中通过自定义shell函数可以定义个人的专属命令


可以关注作者微信公众号,追踪更多有价值的内容!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值