Shell为Linux下的一个脚本语言。主要作用是简化开发,将相应命令组合成逻辑,形成可执行脚本,
然后执行完成逻辑处理。Linux的Shell种类众多,常见的有:
Bourne Shell(/usr/bin/sh或/bin/sh)
Bourne Again Shell(/bin/bash)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
Shell for Root(/sbin/sh)
……
这里主要关注Bash,也就是 Bourne Again Shell,Bash在日常工作中被广泛使用。同时,Bash也是大多数Linux
系统默认的Shell。在一般情况下并不区分Bourne Shell和Bourne Again Shell,所以,像 #!/bin/sh,
它同样也可以改为 #!/bin/bash。#!是一个约定的标记,它告诉Linux系统这个脚本需要什么解释器来执行,
即使用哪一种Shell。
Shell编程的使用基本流程:
1)编写Shell脚本
2)赋予可执行权限
3)执行
eg:
先建一个hello.sh的文件,然后编写脚本内容,这里通过echo命令输出我们最熟悉的Hello,World !
#!/bin/sh
echo "Hello World !"
赋予可执行权限:
chmod a+x hello.sh
执行Shell脚本:
./hello.sh
执行结果:
Hello World!
到这里,我们已经成功完成了第一个Shell脚本!
任何编程语言,都必须有其关键字,Shell也是如此,Shell常用的关键字如下:
echo:打印文字到屏幕 ;
exec:执行另一个 Shell 脚本;
read:读标准输入 ;
expr:可以实现数值运算、数值或字符串比较、字符串匹配、字符串提取、字符串长度计算等功能;
test:用于测试变量是否相等、 是否为空、文件类型等 ;
exit:退出;
eg:新建一个hello2.sh,内容如下:
#!/bin/sh
echo "Hello World!"
# 读入变量
read VAR
echo "VAR is $VAR"
# 计算变量
expr $VAR - 5
# 测试字符串
test "Hello"="HelloWorld"
# 测试整数
test $VAR -eq 10
# 测试目录
test -d ./ios
# 执行其它Shell脚本
exec ./othershell.sh
# 退出
exit
同时,需要新建一个othershell.sh,供exec命令调用,内容如下:
#!/bin/sh
echo "I'm othershell"
运行脚本,中间需要输入read读取的变量值,这里输入100,脚本执行结果如下:
Hello World!
100
VAR is 100
95
I'm othershell
Shell编程,怎么能少了变量呢!Shell变量分为3种:
1、用户自定义变量
2、预定义变量
3、环境变量
变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
1)命名只能使用英文字母,数字和下划线,首个字符不能以数字开头;
2)中间不能有空格,可以使用下划线(_);
3)不能使用标点符号;
4)不能使用bash里的关键字(可用help命令查看保留关键字);
这个命名规则跟Java变量命名规则差不多。
比如: your_name="Hello World!",但是,咱们一般使用的时候变量名都大写。
通过在变量前加$符使用变量,$your_name。
eg:
#!/bin/sh
# 定义变量
your_name="Hello World!"
# 使用变量(这里将变量值输出)
echo $your_name
下面分别看下三种变量怎么玩的?
1、用户自定义变量
这种变量只支持字符串类型,常见3个前缀:
unset:删除变量
readonly:标记只读变量
export:指定全局变量
eg:
#!/bin/sh
# 定义普通变量
CITY=bj
# 定义全局变量
export USERNAME=lanhuigu
# 定义只读变量
readonly AGE=26
# 打印变量的值
echo $CITY
echo $USERNAME
echo $AGE
# 删除CITY变量
unset CITY
# 删除后的变量不能再使用,这里不会再打印出CITY名称
echo $CITY
执行结果:
bj
lanhuigu
26
2、预定义变量
预定义变量常用来获取命令行的输入,常用如下:
$0 :脚本文件名
$1-9 :第1-9个命令行参数名
$# :命令行参数个数
$@ :所有命令行参数
$* :所有命令行参数
$? :前一个命令的退出状态,可用于获取函数返回值
$$ :执行的进程 ID
eg:
#!/bin/sh
echo "print $"
echo "\$0 = $0"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$# = $#"
echo "\$@ = $@"
echo "\$* = $*"
echo "\$$ = $$"
echo "\$? = $?"
执行结果:
print $
# 程序名
$0 = ./var2.sh
# 第一个参数
$1 = 1
# 第二个参数
$2 = 2
# 一共有5个参数
$# = 5
# 打印出所有参数
$@ = 1 2 3 4 5
# 打印出所有参数
$* = 1 2 3 4 5
# 进程 ID
$$ = 15463
# 因为之前没有执行其他命令或者函数,这里打印出0
$? = 0
3. 环境变量
环境变量默认就存在,常用如下:
HOME :用户主目录
PATH :系统环境变量PATH
TERM :当前终端
UID :当前用户ID
PWD :当前工作目录,绝对路径
eg:
echo "print env_var"
echo $HOME
echo $PATH
echo $TERM
echo $PWD
echo $UID
执行结果:
print env_var
# 当前宿主目录
/root
# PATH环境变量
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:
# 当前终端
xterm
# 当前目录
/tmp/yh
# 用户ID
0
在Shell脚本中计算主要掌握4种比较常见的运算方法,功能都是将m + 1:
m=$[ m + 1 ]
m=expr $m + 1 注意:用 “ 字符包起来
let m=m+1
m=$(( m + 1 ))
eg:
#!/bin/bash
m=1
m=$[ m + 1 ]
echo $m
m=`expr $m + 1`
echo $m
# 注意:+ 号左右不要加空格
let m=m+1
echo $m
m=$(( m + 1 ))
echo $m
执行结果:
2
3
4
5
主要包括if、case、for、while、for、until、break、continue。
语法格式:
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
eg:
#!/bin/sh
a=10
b=20
if [$a == $b]
then echo "a等于b"
elif [$a -gt $b]
then echo "a大于b"
elif [ $a -lt $b ]
then echo "a小于b"
else
echo "没有符合条件语句"
fi
执行结果:
a小于b
语法格式:
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
eg:
#!/bin/sh
# 普通 for 循环
for ((i = 1; i <= 3; i++))
do
echo $i
done
# VAR 依次代表每个元素
for VAR in 1 2 3
do
echo $VAR
done
执行结果:
1
2
3
1
2
3
语法格式:
while condition
do
command
done
eg:
#!/bin/sh
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
执行结果:
1
2
3
4
5
语法格式:
until condition
do
command
done
eg:
#!/bin/sh
a=0
until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
执行结果:
0
1
2
3
4
5
6
7
8
9
语法格式:
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
eg:
#!/bin/sh
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
执行结果:
输入 1 到 4 之间的数字:
你输入的数字为:
1
你选择了 1
break命令允许跳出所有循环(终止执行后面的所有循环)。
下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,
需要使用break命令。
eg:
#!/bin/sh
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done
执行结果:
输入 1 到 5 之间的数字:1
你输入的数字为 1!
输入 1 到 5 之间的数字:4
你输入的数字为 4!
输入 1 到 5 之间的数字:5
你输入的数字为 5!
输入 1 到 5 之间的数字:8
你输入的数字不是 1 到 5 之间的! 游戏结束
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。
eg:
#!/bin/sh
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
done
执行结果:
输入 1 到 5 之间的数字: 1
你输入的数字为 1!
输入 1 到 5 之间的数字: 8
你输入的数字不是 1 到 5 之间的!
输入 1 到 5 之间的数字: 2
你输入的数字为 2!
运行代码发现,当输入大于5的数字时,该例中的循环不会结束,语句 echo "游戏结束" 永远不会被执行。
shell函数语法:
[ function ] funname [()]
{
action;
[return int;]
}
说明:
1)可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
2)参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。
return后跟数值n(0-255)。
eg:
#!/bin/sh
# 定义函数
function hello()
{
echo "hello fun"
echo $1 $2
return 1
}
hi()
{
echo "hi fun"
}
# 调用函数
echo "===函数调用开始==="
# 1. 直接用函数名调用hi函数
hi
# 2. 使用[函数名 函数参数]来传递参数
hello 1 2
# 3. 使用[FUN='函数名 函数参数']来间接调用
FUN='hello_world 1 2'
echo $FUN
echo "===函数调用结束==="
# 获取返回值
echo "===获取函数返回值开始==="
hello 1 2
# $? 可用于获取前一个函数的返回值
echo $?
echo "===获取函数返回值结束==="
执行结果:
===函数调用开始===
hi fun
hello fun
1 2
hello_world 1 2
===函数调用结束===
===获取函数返回值开始===
hello fun
1 2
1
===获取函数返回值结束===
检查是否有语法错误:
sh -n script_name.sh
执行并调试 Shell 脚本:
sh -x script_name.sh
任意找一个脚本执行实战一下,比如脚本内容:
#!/bin/sh
m=1
m=$[ m + 1 ]
echo $m
m=`expr $m + 1`
echo $m
# 注意:+ 号左右不要加空格
let m=m+1
echo $m
m=$(( m + 1 ))
echo $m
执行sh -n test.sh ,如果没出现异常,说明脚本没有语法错误问题。
然后执行sh -x test.sh,输出如下内容:
+ m=1
+ m=2
+ echo 2
2
++ expr 2 + 1
+ m=3
+ echo 3
3
+ let m=m+1
+ echo 4
4
+ m=5
+ echo 5
5
带有+表示的是Shell调试器的输出,不带+表示我们程序的输出。