第1章 Shell变量(临时变量、永久变量)
1.1.变量名要求
变量:是shell传递数据的一种方法,用来代表每个取值的符号名。
定义变量时,变量名不加美元符号($),如:
your_name="igeek"
注意,变量名和等号之间不能有空格,和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
- 首个字符必须为字母(a-z,A-Z)。
- 中间不能有空格,可以使用下划线(_)。
- 不能使用标点符号。
- 不能使用bash里的关键字(可用help命令查看保留关键字)。
除了显式地直接赋值,还可以用语句给变量赋值,如:
for file in `ls /etc`
以上语句将 /etc 下目录的文件名循环出来。
1.2.变量分类(临时变量和永久变量)
Shell有两类变量:临时变量和永久变量。
临时变量是shell程序内部定义的,其使用范围仅限于定义它的程序,对其他程序不可见。
永久变量是环境变量,其值不随shell脚本的执行结束而消失。
变量赋值:赋值号“=”两边应没有空格。
定义时赋值,如NUM=1
将一个命令的执行结果赋给变量,如:TIME=`date`
将一个变量赋给另一个变量,如:A=$B
使用echo命令查看变量值。例如:echo $A
TEST="test"
echo $TEST
包含多个字的变量:
$NAME=Mike Ron
运行时出错,应改为:
$NAME="Mike Ron"或$NAME='Mike Ron'
--------------------------------
单引号和双引号的区别:
#$ABC='$NAME Junior'
#echo $ABC
$NAME Junior
单引号之间的内容原封不动地指定给了变量。
删除变量:
#unset NAME
第2章 Shell命令
2.1 Read命令
等待读取输入,直到回车后表示输入完毕
#read name #等待读取输入,直到回车后表示输入完毕,并将输入赋值给变量
HelloWorld #控制台输入Hello
#echo $name #打印变量
HelloWorld
等待一组输入,每个单词之间使用空格隔开,直到回车结束,并分别将单词依次赋值给这三个读入变量。
#read one two three
1 2 3 #在控制台输入1 2 3,它们之间用空格隔开。
#echo "one = $one, two =$two, three = $three"
one = 1, two = 2, three = 3
#read #等待控制台输入,并将结果赋值给特定内置变量REPLY。
2.2 Expr命令
expr命令是一个手工命令行计数器,用于在UNIX/LINUX下求表达式变量的值,一般用于整数值,也可用于字符串。
#计算字串长度
expr length “this is a test”
#抓取字串
expr substr “this is a test” 3 5
#抓取第一个字符数字串出现的位置
expr index "sarasara" a
对整数型变量进行算术运算
expr 3 + 5
expr $var1 - 5
expr $var1 / $var2
expr $var3 \* 10
第3章 变量测试语句
3.1. 文件测试
test -d file 指定文件是否目录
test -f file 指定文件是否常规文件
test -x file 指定文件是否可执行
test -r file 指定文件是否可读
test -w file 指定文件是否可写
test -a file 指定文件是否存在
test -s file 文件的大小是否非0
变量测试语句一般不单独使用,一般做为if语句的测试条件,如:
if test -d file; then
...
fi
说明:判断输入的位置变量1是否是一个目录。
变量测试语句可用[]进行简化,如
test -d $1 等价于 [-d $1]
3.2. 字符串测试
test str1=str2 测试字符串是否相等
test str1!=str2 测试字符串是否不相等
test str1 测试字符串是否不为空
test -n str1 测试字符串是否不为空
test -z str1 测试字符串是否为空
3.3. 整数测试
test int1 -eq int2 测试整数是否相等
test int1 -ge int2 测试int1是否>=int2
test int1 -gt int2 测试int1是否>int2
test int1 -le int2 测试int1是否<=int2
test int1 -lt int2 测试int1是否<int2
test int1 -ne int2 测试两个数是否不相等
第4章 流程控制语句
4.1. shell脚本介绍
shell结构:
1.#!指定执行脚本的shell
2.#注释行
3.命令和控制结构
创建shell程序的步骤:
第一步:创建一个包含命令和控制结构的文件。
第二步:修改这个文件的权限使它可以执行。
使用chmod u+x
第三步:执行 ./example
(也可以使用“sh example”)
位置变量和特殊变量
Shell解释执行用户命令时,将命令行的第一个部分作为命令名,其他部分作为参数。
由出现在命令行上的位置确定的参数称为位置参数。
例如:
1.
ls -l file1 file2 file3
$0 这个程序的文件名ls-l
$n 这个程序的第n个参数值,n=1-9
========================================
特殊变量
$* 这个程序的所有参数
$# 这个程序的参数个数
$$ 这个程序的PID
$! 执行上一个后台命令的PID
$? 执行上一个命令的返回值
执行Shell脚本
方法一:切换到shell脚本所在的目录(此时,称为工作目录)执行shell脚本:
cd /data/shell
./hello.sh
./的意思是说在当前的工作目录下执行hello.sh。如果不加上./,bash可能会响应找到不到hello.sh的错误信息。因为目前的工作目录(/data/shell)可能不在执行程序默认的搜索路径之列,也就是说,不在环境变量PASH的内容之中。查看PATH的内容可用 echo $PASH 命令。现在的/data/shell就不在环境变量PASH中的,所以必须加上./才可执行。
方法二:以绝对路径的方式去执行bash shell脚本:
/data/shell/hello.sh
方法三:直接使用bash 或sh 来执行bashshell脚本:
cd /data/shell
bash hello.sh
或
sh hello.sh
注意,若是以方法三的方式来执行,那么,可以不必事先设定shell的执行权限,甚至都不用写shell文件中的第一行(指定bash路径)。因为方法三是将hello.sh作为参数传给sh(bash)命令来执行的。这时不是hello.sh自己来执行,而是被人家调用执行,所以不要执行权限。
方法四:在当前的shell环境中执行bash shell脚本
cd /data/shell
. hello.sh
或
cd /data/shell
source hello.sh
前三种方法执行shell脚本时都是在当前shell(称为父shell)开启一个子shell环境,此shell脚本就在这个子shell环境中执行。shell脚本执行完后子shell环境随即关闭,然后又回到父shell中。而方法四则是在当前shell中执行的。
4.2. if-else语句
if...then...fi语句
if/else语句
if 条件1 then
命令1
elif 条件2 then
命令2
else
命令3
fi
比较输入的两个数字的大小。首先$#判断是否输入了2个参数。
cat test.sh
#!/bin/sh
if [ $# -ne 2 ]; then
echo "Not enoughparameters"
exit 0
fi
if [ $1 -eq $2 ]; then
echo "$1 equals $2"
elif [ $1 -lt $2 ]; then
echo "$1 littler than$2"
elif [ $1 -gt $2 ]; then
echo "$1 greater than$2"
fi
运行:bash test.sh 1 2
4.3. for-done语句
for...done语句
格式:for 变量 in 名字表
do
命令列表
done
for循环有三种结构:一种是列表for循环,第二种是不带列表for循环。第三种是类C风格的for循环。
4.3.1 列表for循环
例如:
#!/bin/sh
for DAY in Sunday Monday Tuesday Wednesday Thursday Friday Saturday
do
echo "The day is:$DAY"
done
#!/bin/bash
for varible1 in {1..5}
#for varible1 in 1 2 3 4 5
do
echo "Hello, Welcome $varible1 times "
done
do和done之间的命令称为循环体,执行次数和list列表中常数或字符串的个数相同。for循环,首先将in后list列表的第一个常数或字符串赋值给循环变量,然后执行循环体,以此执行list,最后执行done命令后的命令序列。
Shell支持列表for循环使用略写的计数方式,1~5的范围用{1..5}表示(大括号不能去掉,否则会当作一个字符串处理)。
Shell中还支持按规定的步数进行跳跃的方式实现列表for循环,例如计算1~100内所有的奇数之和。
#!/bin/bash
sum=0
for i in {1..100..2}
do
let "sum+=i"
done
echo "sum=$sum"
通过i的按步数2不断递增,计算sum值为2500。同样可以使用seq命令实现按2递增来计算1~100内的所有奇数之和,for iin $(seq 1 2 100),seq表示起始数为1,跳跃的步数为2,结束条件值为100。
4.3.2 不带列表for循环
比较带列表for循环
for循环对字符串进行操作,例如通过for循环显示当前目录下所有的文件。
#!/bin/bash
for file in $( ls )
#for file in *
do
echo "file: $file"
done
也可一使用for file in *,通配符*产生文件名扩展,匹配当前目录下的所有文件。
for通过命令行来传递脚本中for循环列表参数
#!/bin/bash
echo "number of arguments is $#"
echo "What you input is: "
for argument in "$@"
do
echo "$argument"
done
$#表示参数的个数,$@表示参数列表而$*则把所有的参数当作一个字符串显示。
由用户制定参数和参数的个数,与上述的for循环列表参数功能相同。
#!/bin/bash
echo "number of arguments is $#"
echo "What you input is: "
for argument
do
echo "$argument"
done
比上述代码少了$@参数列表,$*参数字符串。
4.3.3 类C风格的for循环
也被称为计次循环
#!/bin/bash
for((integer = 1; integer <= 5; integer++))
do
echo "$integer"
done
for中第一个表达式(integer = 1)是循环变量赋初值的语句,第二个表达式(integer <= 5)决定是否进行循环的表达式,退出状态为非0时将退出for循环执行done后的命令。第三个表达式(integer++)用于改变循环变量的语句。
Shell中不运行使用非整数类型的数作为循环变量,循环条件被忽略则默认的退出状态是0,for((;;))为死循环。
类C的for循环计算1~100内所有的奇数之和。
#!/bin/bash
sum=0
for(( i = 1; i <= 100; i = i + 2 ))
do
let "sum += i"
done
echo "sum=$sum"
4.4. case-esac语句
case...esac语句,格式:
case 变量 in
字符串1) 命令列表1
;;
...
字符串n) 命令列表n
;;
esac
cat case
#!/bin/sh
echo "*******************************"
echo "Please select your operation:"
echo " Press "C" to Copy"
echo " Press "D" to Delete"
echo " Press "B" to Backup"
echo "******************************"
read op
case $op in
C)
echo "your selection isCopy"
;;
D)
echo "your selection isDelete"
;;
B)
echo "your selection isBackup"
;;
*)
echo "invalidateselection"
esac
运行:sh case
4.5. while语句
while语句 格式:
while条件
do
命令
done
#!/bin/sh
num=1
while [ $num -le 10 ]
do
SUM=`expr $num \* $num`
echo $SUM
num=`expr $num + 1`
done
4.6. until语句
until语句,格式:
until 条件
do
命令
done
until类似while循环,不同的是until是条件返回值为假时才继续执行。
第5章 脚本调试
5.1. 调试方法
最简单的调试命令当然是使用echo命令。您可以使用echo在任何怀疑出错的地方打印任何变量值。这也是绝大多数的shell程序员要花费80%的时间来调试程序的原因。Shell程序的好处在于不需要重新编译,插入一个echo命令也不需要多少时间
shell也有一个真实的调试模式。如果在脚本"myscript"中有错误,您可以这样来进行调试:
bash -x myscript
这将执行该脚本并显示所有变量的值。
shell还有一个不需要执行脚本只是检查语法的模式。可以这样使用:
sh -n your_script
这将返回所有语法错误。
Shell提供了一些用于调试脚本的选项,如下所示:
-n
读一遍脚本中的命令但不执行,用于检查脚本中的语法错误
-v
一边执行脚本,一边将执行过的脚本命令打印到标准输出
-x
提供跟踪执行信息,将执行的每一条命令和结果依次打印出来
在命令行提供参数
$ bash -x ./script.sh
总结:
sh -x script
这将执行该脚步并显示所有变量的值
sh -n script
不执行脚本只是检查语法的模式,将返回所有语法错误。