Linux Shell笔记(3)

本次博客主要讲述Linux Shell中的数组、循环和函数。

Shell中的数组

shell中只能定义一维数组,在定义时不需要规定数组的大小,此种规则和C语言有着明显的区别。
shell中定义数组的格式如下:

[数组名]=(value1 value2 value3 ...)

取数组中某个元素的值的格式如下:

${[数组名][下标]}

shell中第一个元素的下标是0,最后一个元素的下标是数组长度减一,数组名代表数组的首个元素。这和C语言中的数组基本性质是相同的。

获取数组中所有元素的格式如下:

${[数组名][*]}${[数组名][@]}

获取当前数组的长度格式如下:

${#[数组名][*]}${#[数组名][@]}

特殊的,获取数组中某个元素(字符串)的长度的命令格式如下:

${#[数组名][下标]}

下面就是一个shell中数组的例子:

#!/bin/bash
#Filename=name.sh

name=(Google Apple HuaWei Tencent Alibaba)

echo "The third string and its length are: " 
echo ${name[2]} ${#name[2]}
echo "The all elements are: "    
echo ${name[*]}
echo "The length of the array name is: " ${#name[*]}

上面的例子就是shell中数组操作的演示,脚本中的name就是这个数组的名字,这个脚本的运行结果如下:

[shallwing@centos ~]$ bash name.sh 
The third string and its length are: 
HuaWei 6
The all elements are: 
Google Apple HuaWei Tencent Alibaba
The length of the array name is:  5

shell中的数组单独使用意义不大,当和循环语句for一起使用时,才可以提现其价值。

Shell中的循环

shell中的循环同C语言类似,也拥有while循环和for循环,只是循环的基本格式同C语言不同罢了。除此之外,shell还具有自己特有的循环语句——until

  • for循环

与C语言中的for循环最不同的是,shell中的for循环只在循环条件为序列的情况下使用,这里说到的序列,一般就是指命令行传来的参数序列或自定义shell数组中所有元素构成的序列

for循环语句的格式如下:

for [变量名] in [数组名 or $* or 序列]
do
	[command 1]
	[command 2]
	...
done

这里也简要地说一下for循环的逻辑,for循环的本质是以序列中的每一个元素为参数,来进行与此相关的操作,所以循环的次数,就很大程度上取决于这个序列的长度。上面for循环语句的格式中,“变量名”的意义在于每一次操作之前,都把序列中对应的那个元素赋值给“变量名”所代表的变量,以便于在循环体里面可以直接引用该变量的值。

for循环常常在shell脚本中用来批量处理某些重复或相似的操作,例如下面shell中批量创建用户的例子:

#!/bin/bash
##FileName=useradd.sh

if [[ `whoami` != "root" ]] ; then
	echo "Permission denied: --only can be run by root!"
	echo "Abort"
	exit
fi

if [[ $# -eq 0 ]] ; then
	echo "Invalid argument: --empty"
	echo "Argument can't be null, please input the users' name!"
	echo "Abort"
	exit
fi


for new_user in $*
do
	check=`cat /etc/passwd | grep $new_user`
	if [[ -z $check ]] ; then
		echo "Input the password of [$new_user]:"
		read -s password
		useradd $new_user  
		echo $password | passwd --stdin $new_user
	else
		echo "$new_user: Already exist!"
		echo "useradd: Fail to create user -- '[$new_user]'\n"
	fi
done

#end

简要地说明一下上面的代码:

  1. Linux中的用户在批量定向创建时,最好由root用户执行,所以一开始需要用ift条件判断和whoami的命令确定当前执行脚本的用户身份;
  2. 执行脚本时,命令行参数不能为空,而且命令行参数传入的是新创建用户的名字;
  3. 传入的参数中,某些用户的名字有可能已经存在,此时就需要进行判断,通过查找/etc/passwd文件中用户的名字来判断名字是否是重复的;
  4. 当判断当前需创建的用户的名字是不存在的时,就可以利用useradd命令来创建用户,并利用passwd命令来设置密码了。
  • while循环

shell中while循环的格式与if条件判断语句的格式是类似的,相当于是先if条件判断一下,然后再决定是否进入循环,其格式如下:

while [[ {条件判断表达式} ]]
do
	[command 1]
	[command 2]
	...
done

当条件判断表达式为“true”时,就可以进入while循环内。利用while循环,可以更灵活地解决一些问题,例如下面的求和shell程序:

#!/bin/bash
##FileName=sum.sh

sum=0
count=0

while [[ $count -le 100 ]]
do
    sum=`expr $sum + $count`
    count=`expr $count + 1`
done

echo "The sum from 0 to 100 is: "${sum}

#end

程序中的“expr”关键字或许有读者不理解,这其实对读懂程序没有太大影响,有关“expr”的用法本人会在(4)中详细说明。以上的sum.sh是不是和C语言中求和的程序比较类似?实际上,这两个程序的算法与思想都是相同的,只是实现的编程语言不同罢了。

while循环语句也可以写出无限循环来,例如:

while true
do
	...
done

while :
do
	...
done
  • until循环

until循环语句的格式与while相同,但是其逻辑恰好与while相反,是当条件判断语句为“false”的条件下才进入循环,当判断语句为“true”时,跳出循环。其格式为:

until [[ {条件判断表达式} ]]
do
	[command 1]
	[command 2]
	...
done
  • 循环的终止与重新开始
    同C语言一样,shell中循环的终止使用关键字break,循环的重新开始使用关键字continue。

Shell中的函数

shell中的函数体的写法相比于C语言来说有所简化,其基本格式如下:

function [函数名](){
	[command 1]
	[command 2]
	...
	(return [变量值])
}

函数调用时,其格式如下:

[函数名] [参数]

对于shell中函数的相关内容,需要注意的是:

  1. shell中函数在书写时,无需像C语言一样,要在函数名后面的圆括号里指定形式参数,函数体内使用形式参数用 $1,$2,$3,… 或 $* 表示,此时的 $n 代表后面调用函数时传入的第n个参数, $* 表示后面调用函数时传入的所有参数构成的序列,其含义与命令行传参类似;
  2. 函数内部定义的变量在程序的任意位置都是有效的
  3. shell中的函数可以使用返回值语句return,但由于shell程序中定义的变量在程序各个地方都是有效的,所以一般不提倡使用return,因为return的值如不立即输出的话,其值会消失;
  4. shell中的函数必须先写完函数体之后,才能调用;
  5. shell函数中可以进行递归调用。

之前给出的求和程序可写成一个函数,例如:

#!/bin/bash

function sum(){
    number=$1
    count=0
    add=0
    while [[ $count -le $number ]] 
    do
        add=`expr $add + $count`
        count=`expr $count + 1`
    done
    return $add
}

sum 100
echo $add

实战运用

  1. 将冒泡法排序的算法用Shell脚本语言实现

冒泡排序算法在C语言学习中是着重进行了分析的,在数据结构中也如此,其对应的算法本人不再赘述,直接给出对应的源码:

#!/bin/bash
#Filename=bubble.sh

if [[ $# -eq 0 ]] ; then
	echo "Invalid argument: Please input some number!"
	exit
fi

num=($*)
len=${#num[*]}

echo "The original array is:"
echo $*

i=0

while [[ $i -lt $len ]] 
do
    j=0
    while [[ $j -lt `expr $len - 1 - $i` ]] 
    do  
        if [[ ${num[$j]} -gt ${num[`expr $j + 1`]} ]] ; then
            temp=${num[$j]}
            num[$j]=${num[`expr $j + 1`]}
            num[`expr $j + 1`]=$temp
        fi
        j=`expr $j + 1`
    done
    i=`expr $i + 1`
done

echo "After ranking, the array is:"
echo ${num[*]}

上面是数组与循环结合使用的例子,代码中由于存在关键字“expr”,增加了代码的复杂性,此时读者直接把expr关键字去掉,则可以很快地读懂代码的逻辑。

  1. 写一个函数,实现递归求n!
#!/bin/bash

echo "Please input a non-negative integer number:"

while read number
do
    if [[ $number -ge 0 ]] ; then
        break
    else
        echo "Invalid number -- negative!"
        echo "Please input again:"
    fi
done

result=1

function factor(){
    if [[ $1 -eq 0 ]] ; then
        return $result
    else
        factor `expr $1 - 1`
        result=`expr $1 \* $result`
    fi
}

factor $number
echo "$number!="$result

上述的代码要完整地写出来实属不易,能够看懂即可。其中\*表示shell中的乘法运算符。

补充

Linux中除了能通过运行shell脚本的方式批量创建用户,同样也可以通过脚本批量删除用户,其对应的脚本如下:

#!/bin/bash
##FileName=userdel.sh

if [[ `whoami` != "root" ]] ; then
	echo "Permission denied: --only can be run by root!"
	echo "Abort"
	exit
fi

if [[ $# -eq 0 ]] ; then 
	echo "Invalid argument: --'empty'"
	echo "Please input the user's name to delete!"
	echo "Abort"
	exit
fi

for users in $*
do
	check=`cat /etc/passwd | grep $users`
	if [[ -z $check ]] ; then
		echo "$users: No such user in '/etc/passwd'"
	else
		userdel -r $users
		echo "$users: delete successfully!"
	fi
done

#end

第三期shell笔记经验分享基本结束,下次将讲述的是shell中小的要点。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值