一、条件测试
1、test 命令 或 [
test 命令或者 [ 可以测试一个条件是否为成立,如果测试结果为真,则该命令的 Exit Status 为 0。如果测试结果为假,则命令的 Exit Status 为1(注意与 C 语言的逻辑表达式正好相反)。
用法:
[ -d DIR ] 如果 DIR 存在并且是一个目录,则为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。
[ -z STRING ] 如果 STRING 的长度为零,则为真。
[ -n STRING ] 如果 STRING 的长度非零,则为真。
[ STRING1 = STRING2 ] 如果两个字符相同,则为真。
[ STRING1 != STRING2 ] 如果字符串不相同,则为真。
[ ARG1 op ARG2 ] ARG1 和 ARG2 应该是整数或取值为整数的变量,op 是 -eq(等于) -ne (不等于) -lt (小于) -le (小于等于) -gt (大于)
-ge(大于等于) 之中的一个。
和 C 语言类似,测试条件之间还可以做与、或、非逻辑运算。
[ ! EXPR ] ! 表示逻辑反
[ EXPR1 -a EXPR2 ] -a 表示逻辑与
[ EXPR1 -o EXPR2 ] -o 表示逻辑或
例如:
VAR=abc
[ -d Desktop -a $VAR = `abc` ]
echo $?
输出: 0
注意:
上例如果没有实现定义好的变量 $VAR ,则 shell 展开为空字符串,会造成测试条件的语法错误(展开为 [ -d Desktop -a = 'abc' ],作为一种好的shell 编程习惯,应该总是把变量取值放在双引号之中。展开为 [ -d Desktop -a " " = ‘abc’ ] )。
unset $VAR 删除定义的本地变量或者环境。
二、 if 语句(分支)
格式:
(1)、单判断:
if ...;then
commands;
fi
注意:这种格式中,if 和 then 在同一行时,条件结尾必须有连着的分号。不在时,则没有。例如:
if [ -f ~/.bahsrc ] ;then 注意:如果 if 条件的后面要紧跟语句的话,那就必须在条件后面添加 分号
.bashrc
fi
(2)、不在同一行时:
if ........
then
commands
fi
(3)、双判断:
if ...;then
commands1
elif ....;then
commands2
else
commands3
fi
(4)、多判断:三层及三层以上的判断,对前面的判断进行扩展。
# -gt -lt -eq -ge -le -ne
# > <>= <=
# $n n 代表个数
# $# 代表参数的个数
# $@ 代表所有的参数的
# $* 代表所有的参数
a=$1
if [ $a -gt 1 ]
then
echo "a>1"
elif [ $a -eq 1 ]
then
echo "a=1"
else
echo "a<1"
fi
for i in "$*"
do
echo "i=$i"
done
# seq 相当于一个集合
for i in $(seq 1 2 10)
do
echo "i=$i"
done
for ((i=0;i<10;i++))
do
echo "i=$i"
done
i=0
while [ $i -lt 10 ]
do
((i++))
echo i=$i
done
num1=10
num2=20
#let sum=$num1+$num2
#sum=$( expr $num1 + $num2 )
sum=$((num1+num2))
echo "sum=$sum"
read -p "please input a num: " num
case $num in
1)
echo "test"
echo "num=1";;
2)
echo "num=2";;
*)
echo "other";;
esac
func()
{
sum=$(($1 + $2))
return $sum
}
func 2 3
ret=$?
echo $ret
三、case/esac 语句(分支)
1、case 命令可以类比 C 语言的 switch/case 语句, esac 表示 case 语句的结束。C 语言的 case 语句只能匹配整型或字符常量表达式,而 shell 脚本的 case 可以匹配字符串和 Wildcard ,每个匹配分支可以有若干条命令,末尾必须以 ;;结束,执行的时候找到 第一个匹配的分支并执行相应的命令,然后直接跳转到 esac 之后,不像 C 语言用 break 跳出分支。
2、用法:
case $arg in
partern | sample )
commands;;
1)
commands1;;
2)
commands2;;
3)
commands3;;
*)
commands4;;
注意:
每行以 ;; 结束。partten 是选择的具体表达式:
* 代表任何字符
? 代表任何字元
[abc] 代表 abc 中的任何一个
[a-n] 代表从 a-n 的任何一个字元
| 代表多重选择
#!/bin/bash
case $1 in
0)
ehco "hello"
echo "param0=0";;
1)
echo "param0=1";;
*)
echo "error";;
esac
四、 for 语句结构
1、结构一: sequnence 格式
for arg in sequnence (实际的变量序列,以空格分开)
do
commands
done
2、结构二:C 语言格式
for ((赋初值;条件;自增/自减))
do
commands
done
!/bin/bash
for i in "1 2 3" "abc"
do
echo $i
done
for i in $(seq 1 2 10)
do
echo "i=${i}"
done
for ((i=0;i<10;i++))
do
echo "i=$i"
done
五、while 语句
while [ 条件 ]
do
command
done
#!/bin/bash
i=0
while [ $i -lt 10 ]
while ((i<10))
do
echo "i=$i"
((i++))
done
六、位置参数和特殊变量
1、常用的位置参数如下:
$0 相当于 C 语言的 main 函数的 argv[0]
$1、$2、$3..... 这些称为位置参数,相当于 C 语言的 main 函数里面的 argv[1]、argv[2].....
$# 相当于 C 语言里面的 main 函数的 argc -1 ,注意这里的 # 后面不表示任何注释
$@ 表示参数列表 "$1","$2",.......... ,例如可以在 for 循环 的 in 后面
$* 表示参数列表 “$1”,"$2",........... 同上。不过这两个表示法有点区别:$@ 和 $*的存储方式不同,$@ 是按每个参数分开(分块)存储的;而, $* 是连续存储在一个块里面
$? 上一条命令的 Exit Status
$$ 当前进程号
shift 左移命令(比如 shift 3 ,表示原来的 $4 变成 $1,原来的 $5 变成 $2 ,原来的 $1,$2,$3 丢弃,$0不移动。不带参的 shift 命令相当于 shift 1)。
七、输入输出
echo 显示文本或变量,或者把字符串输入到文件
echo [option] string
-e 解析转义字符
-n 不回车换行。默认情况下 echo 回显的内容后面跟一个 回车换行
八、管道
| 通过 | 可以把一个命令的输出传递给另一个命令做输入。例如:
ps -ef | grep init
九、tee
tee 把结果输出到标准输出,另一个副本输出到相应的文件中。例如:
ls -l | tee out
十、文件重定向
cmd > file 把标准输出重定向到新文件中
cmd >> file 同上,追加
cmd > file 2&>1 把标准出错也重定向到 1 所指文件里(即把标准出错和标准输出重定向到 文件 file 中)
cmd >> file 2&>1 同上,追加
cmd file 2 输入和输出都重定向到文件里(即 从 file1 文件里输入,输出到 file2 文件中)
cmd <&fd 把文件描述符 fd 作为标准输入
cmd > &fd 把文件描述符 fd 作为标准输出
cmd <&- 关闭标准输出
十一、函数
和 C语言类似,Shell 中也有函数的概念,但是函数定义中没有返回值也没有参数列表。例如:
#!/bin/sh
function sum_func()
{
((sum= $1 + $2))
#echo $sum
return $sum
}
sum_func 22 32
res=$?
echo $res
sad
十一、Shell 脚本的调试方法
shell 脚本调试提供了一些用于调试的选项,如:
-n 读一遍脚本的命令,但不执行,用于检查脚本中的语法错误。
-v 一边执行脚本,一边把执行过的脚本的命令打印到标准出错误并输出。
-x 提供跟踪执行信息,将执行的每一条命令和结果打印出来。