shell编程就是将shell命令写在一个.sh文件里面,类似批处理文件,一次执行多条语句
使用readonly关键字可以建立只读变量,不能修改
readonly mm="ss"
#这条语句报错
mm='ss'
unset 可以删除已经声明的变量
mm ='mm'
unset mm
#这条语句没有输出
echo $mm
shell循环,以下代码实现循环
for skill in Ada Coffe Action Java
do
echo "I am good at ${skill}Script"
done
#输出
I am good at AdaScript
I am good at CoffeScript
I am good at ActionScript
I am good at JavaScript
有一些变量是特殊变量,代表特殊的含义
变量名 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。被双引号(” “)包含时,与$* 稍有不同,下面将会讲到。 |
$? | 上个命令的退出状态,或函数的返回值。 |
$$ | 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 |
shell脚本参数,下例实现传递参数并输出
echo $1
echo $2
#运行 ./test.sh run log
#输出
run
log
$* 和$@的区别
都是表示输入参数的集合,$* 和 $@没有区别,”$*”和”$@”(被双引号包裹起来的)有区别,区别在于,$* 被引号包围时会将连续的若干个引号包围的参数当做一个参数,例如:
#!/bin/bash
echo "\$*=" $*
echo "\"\$*\"=" "$*"
echo "\$@=" $@
echo "\"\$@\"=" "$@"
echo "print each param from \$*"
for var in $*
do
echo "$var"
done
echo "print each param from \$@"
for var in $@
do
echo "$var"
done
echo "print each param from \"\$*\""
for var in "$*"
do
echo "$var"
done
echo "print each param from \"\$@\""
for var in "$@"
do
echo "$var"
done
#执行./test.sh "a" "b" "c" "d",
#输出
$*= a b c d
"$*"= a b c d
$@= a b c d
"$@"= a b c d
print each param from $*
a
b
c
d
print each param from $@
a
b
c
d
print each param from "$*"
a b c d
print each param from "$@"
a
b
c
d
命令替换
命令替换指的是将命令的输出或者返回暂存在变量中,接下来通过输出变量的形式,注意与闭包不同的是这个输出会马上获得,不是接下来调用的时候才执行,示例如下:
a='12'
b=`echo $a`
a='34'
echo $b
#执行./test.sh
#输出12
变量替换
变量 | 替换 |
---|---|
${var} | 变量本来的值 |
${var:-word} | 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。 |
${var:=word} | 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。 |
${var:?message} | 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。若此替换出现在Shell脚本中,那么脚本将停止运行。 |
${var:+word} | 如果变量 var 被定义,那么返回 word,但不改变 var 的值。 |
运算符
shell 默认没有数学运算符,可以使用expr来做数学运算
#!/bin/sh
a=10
b=20
v=`expr $a + $b`
echo "a+b:$v"
v=`expr $a - $b`
echo "a-b:$v"
v=`expr $a \* $b`
echo "a\*b:$v"
v=`expr $b / $a`
echo "b/a:$v"
v=`expr $b % $a`
echo "b%a:$v"
if [ $a == $b ]
then
echo "a is euqal to b"
fi
if [ $a != $b ]
then
echo "a is not equal to b"
fi
#输出
a+b:30
a-b:-10
a\*b:200
b/a:2
b%a:0
运算符之间必须要有空格,可能是因为运算符是用函数实现的,赋值的=和变量之间不能有空格,有了空格就会被当成命令而不是变量,从而显示没有这个命令
shell单引号里面不能引用变量,双引号可以,这里也实现了字符串的拼接,
your_name='liuchenfei'
stra='single quote $your_name'
strb="double quote $your_name"
echo $stra
echo $strb
#输出
single quote $your_name
double quote liuchenfei
${#str}可以计算字符串的长度
your_name="liuchenfei"
echo ${#your_name}
#输出
10
${str:m:n}提取字串m-n个字符
your_name="liuchenfei"
echo ${your_name:1:4}
#输出
iuch
expr查找字串
your_name="liuchenfei"
echo `expr index $liuchenfei chen`
#输出
4
定义数组
array_name=(value0,value1,…………)
或
array_name[0]=value0…………
访问数组
echo ${array_name[n]}#访问第n个元素
echo ${array_name[*]}#访问全部元素,@和*在这里相同
${#list}和${list:m:n}也可以对数组求长度和切片
echo “ff” > myfile 将输出重定向到文件myfile中,终端不再显示输出
可以使用printf 函数类似c语言printf 输出
in="integer"
printf "%d is %s \n" 1 \$in
#输出
1 is integer
if else 语句
shell if else语句的特点是在if下一行要加上then,结尾要加上fi
格式如下:
#if
if [ 条件 ]
then
语句体
fi
#if else
if [ 条件 ]
then
语句体
else
语句体
fi
#if elif
if [条件]
then
语句
elif [条件]
then
语句
fi
比较表达式
表达式 | 含义 | 备注 |
---|---|---|
-eq | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 true。 |
-ne | 检测两个数是否相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | 检测左边的数是否大等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
逻辑表达式
表达式 | 含义 |
---|---|
! | 非 |
-o | 或 |
-a | 与 |
多分支结构
类似switch-case的结构
read a
case a in
1) echo "this is 1"
;;
2) echo "this is 2"
;;
*) echo "this is $a"
;;
esac
#运行
./sw.sh
1
#输出
this is 1
for循环
for val in list
do
语句
done
while循环
while [条件]
do
语句
done
until 循环
#条件成立的时候还执行一次
until [条件]
do
语句
done