Shell脚本第五部分:Bash中的函数

嗨! 欢迎来到HowToForge的shell脚本教程系列。 如果您想阅读本教程的以前版本,请随时点击此处阅读本教程的part1part2part3part4 。 在这部分中,您将学习如何通过创建函数来有效地构建脚本。 在本教程结束之前,您将能够了解如何在Linux Bash Shell中创建函数,将参数传递给函数并将某些值从函数返回到主代码。 让我们开始吧!

介绍

一个函数,也称为编程语言中的子程序是一组指令,用于执行主程序的特定任务[1]。 它允许程序员将一个复杂而冗长的代码打破小部分,可以在需要时调用。 每个函数需要由主程序调用才能运行,因此与代码的其他部分隔离,并创建一个简单的代码测试方法。 此外,函数可以随时重复调用,这样可以重用,优化和最小化代码。 像大多数编程语言一样,bash shell也支持功能。

一般语法:

  1. 语法1:
    function function_name
    {
        ##### set of commands
    }
  2. 语法2:
    function_name()
    {
        #### set of commands
    }

创建功能

bash支持两个功能结构。 在使用第一种语法时,必须使用关键字函数,然后使用函数名称,并打开和关闭括号和花括号,将函数的内容与主例程分开。 如果您在PHP中有背景,那么您将会发现这种语法很熟悉,因为PHP中的函数以相同的方式声明。 其他语法只包含一个函数名称,打开和关闭括号和花括号。

#!/bin/bash
myfunction(){
    echo "My function works!"
}
myfunction

我在我们的例子中使用了第二个语法。 在创建函数myfunction后 ,通过调用其函数名称来调用它的主程序。 我们的脚本中的主要例程将不会被定义为我们的功能的一部分。

现在我们来重新排列我们的代码来测试是否可以在脚本中的任何地方声明函数。 考虑下面的代码:

#!/bin/bash
echo "testing my function"
myfunction

myfunction(){
    echo "My function works!"
}

上面代码中的第3行返回一个未找到的命令错误。 这只意味着:

The function only works if it is declared before your main routine. The interpreter will return an error if you have declared your function after your main routine.

使用函数重构代码

功能最好的功能之一是能够重用代码。 当一个过程需要重复执行命令,但不能使用循环语句来构造时,那么一个函数就可以是一个解决方案。

例如,考虑下面的代码:

#!/bin/bash
while(true)
do
    clear
    printf "Choose from the following operations: \n"
    printf "[a]ddition\n[b]Subtraction\n[c]Multiplication\n[d]Division\n"
    printf "################################\n"
    read -p "Your choice: " choice
    case $choice in
    [aA])
        read -p "Enter first integer: " int1
        read -p "Enter second integer: " int2
        res=$((int1+int2))

    ;;
    [bB])
        read -p "Enter first integer: " int1
        read -p "Enter second integer: " int2
    res=$((int1-int2))

    ;;
    [cC])
        read -p "Enter first integer: " int1
        read -p "Enter second integer: " int2
        res=$((int1*int2))

    ;;
    [dD])
        read -p "Enter first integer: " int1
        read -p "Enter second integer: " int2
        res=$((int1/int2))

    ;;
    *)
        res=0
        echo "wrong choice!"
    esac

    echo "The result is: " $res
    read -p "Do you wish to continue? [y]es or [n]o: " ans
    if [ $ans == 'n' ]
        then
         echo "Exiting the script. Have a nice day!"
        break
    else
        continue
    fi

done

脚本运行良好,但是注意,在switch语句中,每个模式都重复接受输入的行。

#!/bin/bash
inputs(){
     read -p "Enter first integer: " int1
    read -p "Enter second integer: " int2
}

exitPrompt(){
    read -p "Do you wish to continue? [y]es or [n]o: " ans
    if [ $ans == 'n' ]
    then
        echo "Exiting the script. Have a nice day!"
        break
    else
        continue
    fi
}

while(true)
    do
    clear
    printf "Choose from the following operations: \n"
    printf "[a]Addition\n[b]Subtraction\n[c]Multiplication\n[d]Division\n"
    printf "################################\n"
    read -p "Your choice: " choice

    case $choice in
    [aA])
        inputs
        res=$((int1+int2))
    ;;

    [bB])
        inputs
        res=$((int1-int2))
    ;;

    [cC])
        inputs
        res=$((int1*int2))
    ;;

    [dD])
        inputs
        res=$((int1/int2))
    ;;

    *)
        res=0
        echo "wrong choice!"
    esac

    echo "The result is: " $res
    exitPrompt
done

我们通过创建子部分输入exitPrompt来改进我们的代码。 它与我们以前的代码完全一样,但是,由于它的结构正确,我们目前的代码更容易排除故障。

传递函数参数

像大多数编程语言一样,您可以传递参数并在bash的函数中处理这些数据。 下面的代码显示了如何在shell脚本中传递值的过程:

#!/bin/bash
myfunction(){
    echo $1
    echo $2
}

myfunction "Hello" "World"

注意在我们的例子中,我们调用了我的函数后,添加了值“Hello”和“World”。 这些值作为参数传递给myfunction并存储在局部变量中。 然而,与其他语言不同,解释器将传递的值存储到预定义变量中,该变量根据传递参数的顺序命名,1作为起始名称,直到传递顺序。 请注意,“Hello”字存储在变量1中 ,值“World”存储在变量2中

注意:我们示例中的12是局部变量,因此除了传递参数的函数之外,脚本的其他部分不可访问。

例如,

#!/bin/bash
myfunction(){
    echo $1
    echo $2
}

myfunction "Hello" "World"
echo $1
echo $2

我们脚本的最后两行中的echo $ 1和echo $ 2没有显示,因为解释器不会识别这两个变量,因为它们都是本地的函数

从函数返回值

除了创建函数和传递参数之外,bash函数可以通过使用关键字return将函数的局部变量的值传递给主程序。 然后将返回的值存储到默认变量$? 例如,考虑以下代码:

#!/bin/bash
add(){
    sum=$(($1+$2))
    return $sum
}

read -p "Enter an integer: " int1
read -p "Enter an integer: " int2
add $int1 $int2
echo "The result is: " $?

在这个例子中,我们将参数int1和int2传递给add函数。 接下来,add函数通过sum = $(($ 1 + $ 2))来处理它 。 然后,sum变量的值通过行return $ sum传递给主程序。 默认情况下, $ sum的值将存储到默认变量$? 最后,线echo“的结果是:”$? 打印结果。

Note: Shell scripts can only return a single value.

与其他编程语言不同,shell脚本不能从函数返回多个值。 我们来看看这个例子:

#!/bin/bash
add(){
    sum=$(($1+$2))
    dif=$(($1-$2))
    return $sum
}

read -p "Enter an integer: " int1
read -p "Enter an integer: " int2
add $int1 $int2
echo "The result is: " $?
echo "The result is: " $?

把它们加起来

我们还有另一个例子,它使用函数,传递参数并返回值。

#!/bin/bash
#####################
#Author: youcl #
#####################

clear(){
    clear
}

bin(){
    bin1=$(echo "obase=2;$1"|bc)
    echo $bin1
}

dec(){
    dec1=$(echo "ibase=2;$1"|bc)
    return $dec1
}

########Main#########
    printf "Choose from the following operations:\n[1]Decimal to Binary Conversion\n"
    printf "[2]Binary to Decimal Conversion\n"
    read -p "Your choice: " op
    case $op in

    1)
        read -p "Enter integer number: " int
        bin $int
    ;;

    2)
        read -p "Enter binary number: " int
        dec $int
        echo "The decimal equivalent of $int is $?"
    ;;

    *)
        echo "Wrong Choice!"
    esac

给定的示例使用obaseibase命令将给定的输入转换为二进制或十进制值。 行$(echo“obase = 2; $ 1”| bc)将给定的十进制值转换为二进制数字,并将其存储为bin1变量。 接下来我们使用echo命令显示$ bin1的值。

Note: It's better to use echo directly when converting from decimal to binary because when you return command to pass a binary value, the bash converts the binary value to decimal before returning it.

另外,我们使用命令$(echo“ibase = 2; $ 1”| bc)将二进制值转换为十进制数。

您还必须记住,解释器只能接受8位二进制数字。 您将输入超过8位限制的数字,它将产生溢出,数字的最高有效位将被丢弃。

10位二进制数1000001010返回10,因为遵循8位规则,右侧的剩余2位(最高有效位)将被省略,因此,1000001010将变为等于10的00001010。如果您想要一个接受二进制数字超过8位的操作,那么你必须手动创建代码。

结论

Bash具有与编程语言非常相似的功能,可为用户提供大量工具,并使Linux系统更加强大。 在本系列中,您通过功能增强了您在shell脚本中的知识。 shell脚本中的功能为用户提供模块化,使脚本更易于排除故障并启用代码重用。

参考:

[1]美国遗产英语词典,第五版。 版权所有©2011 Houghton Mifflin Harcourt出版公司。 由Houghton Mifflin Harcourt出版公司出版。

赞(52) 打赏
未经允许不得转载:优客志 » 系统运维
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏