Shell脚本基础II

1、shell算术运算
1)加法
r=`expr 4 + 5`(注意! '4' '+' '5' 这三者之间要有空白)
r=$[ 4 + 5 ]
r=$(( 4 + 5 ))
echo $r

2)乘法
r=`expr 4 * 5`
r=$(( 4 * 5 ))
r=$[ 4 * 5 ]
echo $r

3)除法
r=`expr 40 / 5`
r=$(( 40 / 5 ))
r=$[ 40 / 5 ]
echo $r

4)减法
r=`expr 40 - 5`
r=$(( 40 - 5 ))
r=$[ 40 - 5 ]
echo $r

5)求余数
r=$[ 100 % 43 ]
echo $r

6)乘幂(如2的3次方)
r=$(( 2 ** 3 ))
r=$[ 2 ** 3 ]
echo $r
注:expr 沒有乘幂

7)使用let命令
加法:
n=10
let n=n+1
echo $n #n=11

乘法:
let m=n*10
echo $m

除法:
let r=m/10
echo $r

求余数:
let r=m%7
echo $r

乘冪:
let r=2**2
echo $r


2、利用test指令的测试功能
1)关于某个档名的类型侦测(存在与否),如:test -e filename
-e  该『档名』是否存在?
-f  该『档名』是否为档案(file)?
-d  该『文件名』是否为目录(directory)?
-b  该『文件名』是否为一个 block device 装置?
-c  该『文件名』是否为一个 character device 装置?
-S  该『档名』是否为一个 Socket 档案?
-p  该『档名』是否为一个 FIFO (pipe) 档案?
-L  该『档名』是否为一个连结档?

2)关于档案的权限侦测,如:test -r filename
-r  侦测该文件名是否具有『可读』的属性?
-w  侦测该档名是否具有『可写』的属性?
-x  侦测该档名是否具有『可执行』的属性?
-u  侦测该文件名是否具有『SUID』的属性?
-g  侦测该文件名是否具有『SGID』的属性?
-k  侦测该文件名是否具有『Sticky bit』的属性?
-s  侦测该档名是否为『非空白档案』?

3)两个档案之间的比较,如:test file1 -nt file2
-nt  (newer than)判断file1是否比file2新
-ot  (older than)判断file1是否比file2旧
-ef  判断file2与file2是否为同一档案,可用在判断hard link的判定上。主要意义在判定两个档案是否均指向同一个inode

4)关于两个整数之间的判定,如:test n1 -eq n2
-eq  两数值相等(equal)
-ne  两数值不等(not equal)
-gt  n1大于n2(greater than)
-lt  n1小于n2(less than)
-ge  n1大于等于n2(greater than or equal)
-le  n1小于等于n2(less than or equal)

5)判定字符串的数据
test -z string  判定字符串是否为0?若string为空字符串,则为true
test -n string  判定字符串是否非为0?若string为空字符串,则为false。
注:-n亦可省略
test str1 = str2 判定str1是否等于str2,若相等,则回传true
test str1 != str2 判定str1是否不等于str2,若相等,则回传false

6)多重条件判定,例如:test -r filename -a -x filename
-a (and)两状况同时成立!例如test -r file -a -x file,则file同时具有r与x权限时才回传true。
-o (or)两状况任何一个成立!例如test -r file -o -x file,则file具有r或x权限时就可回传true。
! 反相状态,如test ! -x file,当file不具有x时回传true。

[root@linux scripts]# vi sh05.sh
#!/bin/bash
# Program:
#  Let user input a filename, the program will search the filename
#  1.) exist? 2.) file/directory? 3.) file permissions
# History:
# 2005/08/25  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#让使用者输入档名,并且判断使用者是否真的有输入字符串?
echo -e "The program will show you that filename is exist whichinput by you. "
read -p "Input a filename : " filename
test -z $filename && echo "You MUST input a filename." && exit 0
#判断档案是否存在?
test ! -e $filename && echo "The filename $filename DO NOT exist" && exit 0
#开始判断档案类型与属性
test -f $filename && filetype="regulare file"
test -d $filename && filetype="directory"
test -r $filename && perm="readable"
test -w $filename && perm="$perm writable"
test -x $filename && perm="$perm executable"
#开始输出信息
echo "The filename: $filename is a $filetype"
echo "And the permission are : $perm"

3、利用判断符号[ ]的测试功能
   除了我们很喜欢使用的test之外,其实还可以利用判断符号[ ]来进行数据的判断。
[root@linux ~]# [ -z "$HOME" ]
[ "$HOME" == "$MAIL" ]
[□"$HOME"□==□"$MAIL"□] 
↑           ↑    ↑          ↑
注意:
1)在中括号[]内的每个组件都需要有空格键来分隔;
2)在中括号内的变量最好都以双引号来设定;
3)在中括号内的常数最好都以单或双引号来设定。
[root@linux scripts]# vi sh06.sh
#!/bin/bash
# Program:
#  This program will show the user's choice
# History:
# 2005/08/25  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input (Y/N): " yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt!" && exit 0
echo "I don't know what is your choise" && exit 0
 

4、Shell script的预设变量($0, $1...)
[root@linux scripts]# vi sh07.sh
#!/bin/bash
# Program:
#  The program will show it's name and first 3 parameters.
# History:
# 2005/08/25  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "The script naem is ==> $0"
[ -n "$1" ] && echo "The 1st paramter is ==> $1" || exit 0
[ -n "$2" ] && echo "The 2nd paramter is ==> $2" || exit 0
[ -n "$3" ] && echo "The 3th paramter is ==> $3" || exit 0

[root@linux scripts]# sh sh07.sh theone haha quot
The script naem is ==> sh07.sh
The 1st paramter is ==> theone
The 2nd paramter is ==> haha
The 3th paramter is ==> quot


5、条件判断式
1)利用if .... then
格式1:
if [ 条件判断式 ]; then
当条件判断式成立时,可以进行的指令工作内容;
fi
例子:
[root@linux scripts]# vi sh06-2.sh
#!/bin/bash
# Program:
#  This program will show the user's choice
# History:
# 2005/08/25  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input (Y/N): " yn
if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
echo "OK, continue"
exit 0
fi
if [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
echo "Oh, interrupt!"
exit 0
fi
echo "I don't know what is your choise" && exit 0

格式2:
if [ 条件判断式 ]; then
当条件判断式成立时,可以进行的指令工作内容;
else
当条件判断式不成立时,可以进行的指令工作内容;
fi

如果考虑更复杂的情况,则可以使用这个语法:
if [ 条件判断式一 ]; then
当条件判断式一成立时,可以进行的指令工作内容;
elif [ 条件判断式二 ]; then
当条件判断式二成立时,可以进行的指令工作内容;
else
当条件判断式一与二均不成立时,可以进行的指令工作内容;
fi

例子:
[root@linux scripts]# vi sh06-3.sh
#!/bin/bash
# Program:
#  This program will show the user's choice
# History:
# 2005/08/25  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input (Y/N): " yn
if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
echo "OK, continue"
elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
echo "Oh, interrupt!"
else
echo "I don't know what is your choise"
fi


2)利用case ..... esac判断
格式:

case $变量名称 in
"第一个变量内容")
程序段
;;
"第二个变量内容")
程序段
;;
*)
不包含第一个变量内容与第二个变量内容的其它程序执行段
exit 1
;;
esac

例子:
[root@linux scripts]# vi sh08-2.sh
#!/bin/bash
# Program:
#  Show "Hello" from $1.... by using case .... esac
# History:
# 2005/08/29  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
case $1 in
"hello")
echo "Hello, how are you ?"
;;
"")
echo "You MUST input parameters, ex> $0 someword"
;;
*)
echo "Usage $0 {hello}"
;;
esac

一般来说,使用『case $变量 in』或类似语法中,当中的那个 $变量 大致有两种取得的方式:
直接下达式:例如上面提到的,利用『script.sh variable』的方式来直接给予$1这个变量的内容,这也是在/etc/init.d目录下大多数程序的设计方式。
交互式:透过read这个指令来让使用者输入变量的内容。
 
3、function功能
   function也是拥有内建变量的~他的内建变量与shell script很类似,函数名称代表示$0,而后续接的变量也是$1, $2...
格式:
function fname() {
程序段
}

例子:
[root@linux scripts]# vi sh11-3.sh
#!/bin/bash
# Program:
#  Let user input one, two, three and show in screen.
# History:
# 2005/08/29  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
function printit(){
echo "Your choice is $1"
}
echo "This program will print your selection !"
case $1 in
"one")
printit 1
;;
"two")
printit 2
;;
"three")
printit 3
;;
*)
echo "Usage {one|two|three}"
;;
esac


4、循环
1)while do done, until do done
格式:
while [ condition ]
do
程序段落
done
    这种方式中,while是『当....时』,所以,这种方式是当condition条件成立时,就进行循环直到condition条件不成立才停止。

until [ condition ]
do
程序段落
done
这种方式恰恰与while相反,是当condition条件成立时就终止循环,否则就持续进行循环的程序段

例子:
[root@linux scripts]# vi sh13.sh
#!/bin/bash
# Program:
#  Try to use loop to calculate the result "1+2+3...+100"
# History:
# 2005/08/29  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
s=0
i=0
while [ "$i" != "100" ]
do
i=$(($i+1))
s=$(($s+$i))
done
echo "The result of '1+2+3+...+100' is ==> $s"

[root@linux scripts]# vi sh12-2.sh
#!/bin/bash
# Program:
#  Use loop to try find your input.
# History:
# 2005/08/29  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
until [ "$yn" == "yes" ] || [ "$yn" == "YES" ]
do
read -p "Please input yes/YES to stop this program: " yn
done


2)for(( ))...do....done
格式:
for (( 初始值; 限制值; 执行步阶 ))
do
程序段
done

例子:
[root@linux scripts]# vi sh14.sh
#!/bin/bash
# Program:
#  Try do calculate 1+2+....+100
# History:
# 2005/08/29  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
s=0
for (( i=1; i<=100; i=i+1 ))
do
s=$(($s+$i))
done
echo "The result of '1+2+3+...+100' is ==> $s"


3)for...in...do...done
格式:
for var in con1 con2 con3 ...
do
程序段
done
1.  第一次循环时, $var 的内容为 con1 ;
2.  第二次循环时, $var 的内容为 con2 ;
3.  第三次循环时, $var 的内容为 con3 ;
4.  ....

例子:
[root@linux scripts]# vi sh16.sh
#!/bin/bash
# Program:
#  let user input a directory and find the whole file's permission.
# History:
# 2005/08/29  VBird  First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#先看看这个目录是否存在?
read -p "Please input a directory: " dir
if [ "$dir" == "" ] || [ ! -d "$dir" ]; then
echo "The $dir is NOT exist in your system."
exit 1
fi
#开始测试档案
filelist=`ls $dir`
for filename in $filelist
do
perm=""
test -r "$dir/$filename" && perm="$perm readable"
test -w "$dir/$filename" && perm="$perm writable"
test -x "$dir/$filename" && perm="$perm executable"
echo "The file $dir/$filename's permission is $perm "
done

5、shell script的追踪与debug
[root@linux ~]# sh [-nvx] scripts.sh
参数:
-n:不执行script,仅查询语法的问题;
-v:执行sccript前,先将scripts的内容输出到屏幕上;
-x:将使用到的script内容显示到屏幕上。

范例一:测试sh16.sh有无语法的问题?
[root@linux ~]# sh -n sh16.sh
   若语法没有问题,则不会显示任何信息。

范例二:将sh15.sh的执行过程全部列出来
[root@linux ~]# sh -x sh15.sh
+ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/home/vbird/bin
+ export PATH
+ for animal in dog cat elephant
+ echo 'There are dogs.... '
There are dogs....
+ for animal in dog cat elephant
+ echo 'There are cats.... '
There are cats....
+ for animal in dog cat elephant
+ echo 'There are elephants.... '
There are elephants....
   使用-x真的是追踪script的好方法,他可以将所有有执行的程序段在执行前列出来,如果是程序段落,则输出时最前面会加上+字号,表示他是程序代码,实际的输出则与standard output。

原文地址:https://www.cnblogs.com/defias/p/3427392.html