本次博客主要讲述Linux 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中的循环同C语言类似,也拥有while循环和for循环,只是循环的基本格式同C语言不同罢了。除此之外,shell还具有自己特有的循环语句——until
与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
简要地说明一下上面的代码:
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循环语句的格式与while相同,但是其逻辑恰好与while相反,是当条件判断语句为“false”的条件下才进入循环,当判断语句为“true”时,跳出循环。其格式为:
until [[ {条件判断表达式} ]]
do
[command 1]
[command 2]
...
done
shell中的函数体的写法相比于C语言来说有所简化,其基本格式如下:
function [函数名](){
[command 1]
[command 2]
...
(return [变量值])
}
函数调用时,其格式如下:
[函数名] [参数]
对于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
冒泡排序算法在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关键字去掉,则可以很快地读懂代码的逻辑。
#!/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中小的要点。