目录
一、shell script里常用的几个命令
1、expr命令
这个命令可以对整数表达式进行运算。注意,运算符前后必须要有空格符
[hyxy@master ~]$ expr 1 + 2
3
[hyxy@master ~]$ expr 12 - 10
2
[hyxy@master ~]$ expr 3 \* 4 <==乘号需要转义字符进行转义
12
[hyxy@master ~]$ expr 6 / 4 <==只能进行整除运算
1
[hyxy@master ~]$ expr `expr 3 + 9` / 3 <== 嵌套或者是给变量赋值时,使用反单引号
4
[hyxy@master ~]$ n=3
[hyxy@master ~]$ m=9
[hyxy@master ~]$ result=`expr \`expr $n + $m \` / 4` <==反单引号嵌套时要使用转义字符
[hyxy@master ~]$ echo $result
3
或者使用选项可以对字符串进行一些计算
[hyxy@master ~]$ expr index "hello linux" ol <==计算匹配字符第一次出现的位置序号,从1开始哦
3
[hyxy@master ~]$ expr substr "hello linux" 2 3 <==截取字符串,从第2个开始截取,截取3个长度
ell
[hyxy@master ~]$ expr length "hello linux" <==计算字符串的长度
11
[hyxy@master ~]$ expr match “hello linux” "he" <==计算两个字符串从头匹配上的字符个数
2
2、echo命令
echo命令用于输出显示一行数据。
[hyxy@master ~]$ name=kitty
[hyxy@master ~]$ echo $name
kitty
[hyxy@master ~]$ echo this is a test
this is a test
可以使用-e ,让转义字符串生效
[hyxy@master ~]$ echo "hello\nworld"
hello\nworld
[hyxy@master ~]$ echo -e "hello\nworld" <== \n 表示换行
hello
world
[hyxy@master ~]$ echo -e "hello\nworld\c" <== \c 表示不换行
hello
world[hyxy@master ~]$
3、printf命令
与echo命令功能相同,用来输出显示数据。功能更强大,可以格式化字符串,指定字符串的宽度,左右对齐方式等等。默认情况下不换行,可以手动添加\n
语法: printf format [arguments……...]
说明: format: 格式控制字符串
arguments: 参数值列表
格式控制字符 | 表示含义 | 转义字符 | 表示含义 | |
---|---|---|---|---|
%s | 字符串 | \a | 警告字符,通常为ASCII的BEL字符 | |
%f | 对应位置必须是浮点数。否则报错 | \b | 后退 | |
%c | ASCII字符,即显示对应参数的第一个字符 | \f | 换页 | |
%d,%i | 十进制整数 | \n | 换行 | |
%o | 八进制值 | \r | 回车 | |
%u | 不带正负号的十进制值 | \t | 水平制表符 | |
%x | 十六进制值(a-f) | \v | 垂直制表符 | |
%X | 十六进制值(A-F) | \\ | 表示\本身 | |
%% | 表示%本身 |
直接看示范案例:
[hyxy@master ~]$ printf "%s\n" 1 2 3 10
1
2
3
10
[hyxy@master ~]$ printf "%.2f\n" 1 2 3 10
1.00
2.00
3.00
10.00
[hyxy@master ~]$ printf " (%s) " 1 2 3 10;echo
(1) (2) (3) (10)
[hyxy@master ~]$ printf "%s %s %s\n" 1 2 3 4 <==#多出的参数会重用之前的格式
1 2 3
4
[hyxy@master ~]$ printf "%-10s %-10s %-4s %-4s \n" 姓名 性别 年龄 体重kg 张三 男 23 70 王红 女 18 45
姓名 性别 年龄 体重kg
张三 男 23 70
王红 女 18 45
[hyxy@master ~]$ printf "%x\n" 43 <==将十进制43转成十六进制
2b
4、test命令
用于检测文件类型、文件属性、整数、字符串等操作
文件类型检测 | |
---|---|
test -e filename | 检测filename是否存在 |
test -d filename | 检测filename是不是目录 |
test -f filename | 检测filename是不是普通文件 |
test -L filename | 检测filename是不是软链接文件 |
文件属性检测 | |
test -r filename | 检测filename是否有可读权限 |
test -w filename | 检测filename是否有可写权限 |
test -x filename | 检测filename是否有执行权限 |
两个文件的比较 | |
test file1 -nt file2 | 检测 file1 是否比 file2 新 |
test file1 -ot file2 | 检测 file1 是否比 file2 旧 |
test file1 -ef file2 | 检测 file1和 file2 是否为同一文件 |
两个整数的比较 | |
test n1 -eq n2 | 检测 n1 与 n2 是否相等 |
test n1 -ne n2 | 检测n1 与 n2 是否不等 |
test n1 -gt n2 | 检测n1 是否大于 n2 (greater than) |
test n1 -lt n2 | 检测n1 是否小于 n2 (less than) |
test n1 -ge n2 | 检测n1 是否大于等于n2 |
test n1 -le n2 | 检测n1 是否小于等于n2 |
字符串的数据 | |
test -z string | 检测string 是否为空 |
test -n string | 检测string 是否不为空 -n 也可以省略 |
test string1 == string2 | 检测string1与string2是否相等 |
test string1 != string2 | 检测string1与string2 是否不想等 |
多条件连接 test -r filename -a -x filename | |
-a | and,两个检测都成立,返回true |
-o | or,只要有一个检测成立,就返回true |
! | 非 |
通常test命令不单独使用,而是与if语句连用,或者是放在循环结构中。
5、判断符号[]
除了好用的test外,我们还可以使用中括号来进行检测条件是否成立。
举例说明
[ -r filename ] : 检测filename是否有可读权限
[ -f filename -a -r filename ] : 检测filename是不是普通文件并且有可读权限
二、流程控制语句
shell script中,也支持像其他编程语言常用到的流程控制语句,如if,while等等。
1、if分支结构
只有一个条件表达式的写法:
写法1:
if [ 条件表达式 ] ;then
#条件成立时,要执行的作业内容
fi
写法2:
if [ 条件表达式 ] ;then
#条件成立时,要执行的作业内容
else
#条件不成立时,要执行的作业内容
fi
if中的判断符号后的分号[;],也可以使用[enter]键来替换。 fi是if的倒写形式,是if分支结构结束的含义。
[hyxy@master ~]$ vim test.sh
#!/bin/bash
if [ -d "/home" ];then
echo "this is a directory"
else
echo "this is not a directory"
fi
[hyxy@master ~]$ sh test.sh
this is a directory
有多个条件表达式的写法:
if [ 条件表达式1 ] ;then
#条件1成立时,要执行的作业内容
elif [ 条件表达式2 ] ;then
#条件2成立时,要执行的作业内容
fi
[hyxy@master ~]$ vim test.sh
#!/bin/bash
m=10 n=11 x=4 y=5
if [ $m -gt $n ];then
echo "m>n"
elif [ $m -lt $n -a $x -lt $y ];then #多条件可以使用 -a/-o连接
echo "m<n&&x<y"
elif [ $m -le $n ] || [$x -eq $y ];then #每个条件一个[],使用&&/||连接
echo "m<=n&&x<=y"
fi
[hyxy@master ~]$ sh test.sh
m<n&&x<y
当然可以嵌套使用,这里就不举例了。
2、case..in语句
也可以利用case..in语句,进行匹配,选择匹配成功的那块进行作业。
格式:
case $variable in
值1)
#作业内容
;; <==两个分号,表示这个作业结束
值2)
#作业内容
;;
esac <==esac是倒着写的case,结束case..in结构的作用
[hyxy@master ~]$ vim test.sh
#!/bin/bash
case $1 in
"hello")
echo "hello,welcome to china"
;;
"")
echo "you must input parameters"
;;
*) # 通配符*
echo "your command is $0"
;;
esac
[hyxy@master ~]$ sh test.sh
you must input parameters
3、while循环结构
while循环结构:当条件成立时,就循环执行作业内容。
格式:
while [ 条件表达式 ]
do
#作业内容
done
[hyxy@master ~]$ vim test.sh
#!/bin/bash
while [ "${input}" != "yes" -a "${input}" != "YES" ]
do
read -p "please input yes/YES to stop:" input
done
echo "your input is :${input}"
[hyxy@master ~]$ sh test.sh
please input yes/YES to stop:hello
please input yes/YES to stop:kitty
please input yes/YES to stop:yes #输入yes终止循环
your input is :yes
4、until循环结构
until循环结构:当条件成立时,就终止循环,条件不成立时,就一直循环下去。
格式:
until [ 条件表达式 ]
do
#作业内容
done
我们使用until循环结构修改while循环结构的案例:
[hyxy@master ~]$ vim test.sh
#!/bin/bash
until [ "${input}" == "yes" -o "${input}" == "YES" ]
do
read -p "please input yes/YES to stop:" input
done
echo "your input is :${input}"
[hyxy@master ~]$ sh test.sh
please input yes/YES to stop:a
please input yes/YES to stop:b
please input yes/YES to stop:yes
your input is :yes
在循环结构中,我们使用以下两个关键字:
break: 如果想要提前结束循环(即想跳出循环) 使用关键字
continue: 如果想结束当次循环,进行下一次循环 使用关键字
[hyxy@master ~]$ vim test.sh
#!/bin/bash
num=1
until [ "${input}" == "yes" -o "${input}" == "YES" ]
do
read -p "please input yes/YES to stop:" input
let num++
if [ $num -gt 5 ];then
echo "your count of input is out of 10,auto stop"
break <== 跳出,结束循环
fi
done
echo "your input is :${input}"
[hyxy@master ~]$ sh test.sh
please input yes/YES to stop:1
please input yes/YES to stop:1
please input yes/YES to stop:1
please input yes/YES to stop:1
please input yes/YES to stop:1
your count of input is out of 10,auto stop
your input is :1
5、for循环结构
while,until循环结构适合不知道循环次数的情况。而知道循环次数的情况下,for循环结构就比较合适了
语法:
for variable in 列表
do
#作业内容
done
直接上案例
#!/bin/bash
for day in monday tuesday wenseday thursday friday saturday sunday
do
echo " today is $day"
done
#!/bin/bash
files=$(ls ~)
for filename in ${files}
do
echo "filename is $filename"
done
#!/bin/bash
for num in $(seq 1 100)
do
echo "$num"
done
#!/bin/bash
for username in $(cut -d ':' -f1 /etc/passwd)
do
echo "username is :$username"
done
for循环还有另外一种写法,适合在数值的处理上使用
格式:
for (( 变量初始化;条件限定;变量改变方向 ))
do
#作业内容
done
#!/bin/bash
sum=0
for ((i=0;i<=10;i++))
do
#sum=$[ $sum + $i ]
sum=$(( $sum + $i ))
done
echo $sum
6、select表单循环
有的时候,需要将一些数据设置成表单的模式,供用户来选择。我们就可以使用select表单循环结构
格式:
for variable in 列表
do
#作业内容
done
也直接上案例演示
#!/bin/bash
select var in monday tuesday wenseday thursday friday saturday sunday
do
echo "your option is $var"
if [ $var == "sunday" ];then
break
fi
done
[hyxy@master ~]$ sh test.sh
1) monday 3) wenseday 5) friday 7) sunday
2) tuesday 4) thursday 6) saturday
#? 2
your option is tuesday
#? 1
your option is monday
#? 2
your option is tuesday
#? 7
your option is sunday #然后退出
[hyxy@master ~]$
7、shift指令
shift这个单词,在计算机中,有“使数据产生位移”的含义。对于linux系统来说,在shell中,shift命令可以使参数产生位移。我通过案例来给大家解释一下:
[hyxy@master ~]$ vim test.sh
#!/bin/bash
echo "all parameters ========>: $@"
echo "the first parameters ==>: $1"
echo "---------------------黄金分割线---------------------------"
shift
echo "all parameters ========>: $@"
echo "the first parameters ==>: $1"
echo "---------------------黄金分割线---------------------------"
shift
echo "all parameters ========>: $@"
echo "the first parameters ==>: $1"
echo "---------------------黄金分割线---------------------------"
shift
echo "all parameters ========>: $@"
echo "the first parameters ==>: $1"
运行这个shell script,试试看
[hyxy@master ~]$ sh test.sh one two three four #四个参数
all parameters ========>: one two three four
the first parameters ==>: one
---------------------黄金分割线---------------------------
all parameters ========>: two three four #shift后,剩下三个参数
the first parameters ==>: two
---------------------黄金分割线---------------------------
all parameters ========>: three four #shift后,剩下两个个参数
the first parameters ==>: three
---------------------黄金分割线---------------------------
all parameters ========>: four #shift后,剩下一个参数
the first parameters ==>: four
再看看这个案例:计算参数的总和
[hyxy@master ~]$ vim test.sh
#!/bin/bash
sum=0
until [ "$1" == "" ]
do
sum=`expr $sum + $1 `
shift #使参数向左移动
done
echo "sum:$sum"
运行结果如下:
[hyxy@master ~]$ sh test.sh 1 2 3 4
sum:10
三、函数的应用
在shell script中,也支持函数的使用,这样可以更方便重用作业逻辑,简化我们的程序代码
格式:
function funcName(){
#作业内容
}
注意:
1、关键字function 可加可不加
2、调用时,直接写函数名称,不添加()。
3、因为script是从上往下,从左往右执行的,所以,要先定义,后调用
4、return关键字,可加可不加,看需求
加的话,返回值只能是0~255的整数,使用$?获取返回值
6、可以使用$n位置参数变量向函数里传值
看案例,来学习是最简单有效的方式哦!
应用案例1:
#!/bin/bash
function sum(){
a=0
for i in {1..100}
do
a=$[a+i]
done
echo "1~100 的和:$a"
}
sum # 调用函数sum
[hyxy@master ~]$ sh test.sh #执行script
1~100 的和:5050
[hyxy@master ~]$ source ./test.sh #另外一种执行方式
1~100 的和:5050
[hyxy@master ~]$ sum #因为test.sh已经引入此bash中,因此可以直接写函数调用了,是不是很方便
1~100 的和:5050
应用案例2:
#!/bin/bash
function f1(){
sum=0
for i in {1..100}
do
sum=$[sum+i]
done
echo "sum的结果是:$sum "
x=200
y=2
return $[x+y] #可以带有return关键字,规定函数的返回值
}
f1 #调用函数
result=$? #调用后函数的返回值,必须使用$?来读取
echo "result:$result"
[hyxy@master ~]$ sh test.sh
sum的结果是:5050
result:202 #函数的返回结果
这里强调一下:函数的返回值的范围:0~255。不会超过这个范围的。
应用案例3:
#!/bin/bash
function pr(){
echo -n "your choise is "
}
echo "this programe is print your choise"
select var in monday tuesday wenseday thursday friday saturday sunday q
do
pr; echo $var
if [ "$var" == "q" ] ;then
break
fi
done
[hyxy@master ~]$ sh test.sh
this programe is print your choise
1) monday 3) wenseday 5) friday 7) sunday
2) tuesday 4) thursday 6) saturday 8) q
#? 1
your choise is monday
#? 2
your choise is tuesday
#? 8
your choise is q
应用案例4:
#!/bin/bash
function f1(){
sum=$[ $1 + $2 ]
return $sum
}
f1 10 20
echo "f1执行结果:$?"
[hyxy@master ~]$ sh test.sh
f1执行结果:30
[hyxy@master ~]$ source ./test.sh #将脚本引入bash环境下
f1执行结果:30
[hyxy@master ~]$ f1 20 40 #函数可以看成命令来执行
[hyxy@master ~]$ echo $?
60
四、script之间的引入
shell script内部也可以引用其他外部脚本,这样可以很方便的封装一些公用的代码作为一个独立的文件。
shell script引用外部脚本语法如下:
. fileName # .与文件之间一定要有空格
或者
source fileName
看下面案例:
1、在test.sh里定义函数f1
[hyxy@master ~]$ vim test.sh #在test.sh定义一个函数
#!/bin/bash
function f1(){
sum=$[ $1 + $2 ]
echo "sum of the two number is:$sum"
}
2、在test1.sh里引入test.sh
[hyxy@master ~]$ vim test1.sh
#!/bin/bash
. ~/test.sh #在test1.sh里引入test.sh脚本
f1 10 10 #使用test.sh里的函数f1
3、执行test1.sh
[hyxy@master ~]$ sh test1.sh
sum of the two number is:20 #函数f1的逻辑
五、shell script的追踪与debug
我们可以使用下面的语法来进行脚本的追踪与debug
sh [选项] *.sh
选项介绍:
-n:不执行script,仅仅检查语法的问题
-v:不执行script,仅仅将script里的内容显示在屏幕上
-x:显示script里的重要数据,并执行script
[hyxy@master ~]$ vim test.sh
#!/bin/bash
function f1(){
sum=$[ $1 + $2 ]
echo "sum of the two number is:$sum"
}
name=nihao
yn=yes
for var in one two three
do
echo $var
done
测试一下:
[hyxy@master ~]$ sh -x test.sh
+ name=nihao
+ yn=yes
+ for var in one two three
+ echo one
one
+ for var in one two three
+ echo two
two
+ for var in one two three
+ echo three
three
小总结:到这里 shell script就整理完了,在shell编程上,要多看,多练,才会更加纯熟。