基本格式
Shell脚本的扩展名为.sh
,通常格式如下
#!/bin/bash
(其他语句)
第一句话#!/bin/bash
是必然的.
在编写完Shell脚本之后,我们可以输入./xxx.sh
来执行.
但是你会发现你实际上执行不了,因为你没有执行的权限.用ls -l xxx.sh
命令,你可以看到权限是-rw-rw-rw-
.
这时可以使用chmod
命令来改变权限,例如chmod 777 xxx.sh
(chmod相关内容自行了解).
变量
shell脚本中的变量在定义的时候可以直接用一个名字,但是在使用的时候需要在前面加一个$
号.
注意是$变量名
而不是$(变量名)
,这个和makefile不一样.
同时,变量在赋值的时候不能在=
的两端加空格.你需要a=1
而不是a = 1
.
但是$0,$1...$n
这些变量是钦定的,他们是你调用脚本时在命令行输入的参数.其中$0
是脚本的名称(有点像C语言).
$#
也是钦定的,他是参数的数量.
$@
也是钦定的,他是所有参数,写了这个相当于写了$0,$1,...$n
,例子:
#!/bin/bash
echo "num of arguements is :" $#
echo "first arguement is :" $1
echo "all argument is :" $@
这个代码会输出参数的个数,第一个参数(不算$0
),以及列出所有参数.
表达式
shell脚本支持整数运算,表达式的格式是$((表达式))
.例如
a=1
b=2
c=$(($a+$b))
没错,在这个表达式里面的变量还是要加$
.
交互
输出
Shell的输出使用echo
命令,如下(他会换行)
echo "hello world"
输入
Shell的输入使用read
命令,你可以同时输入多个变量,例如
read a b c
注意,不用加,
,一个空格隔开就行.
你也可以在输入的时候,使用-p
选项输出一些提示信息,例如
read -p "wdnmd" a
你就会看到这样的效果:
wdnmd<等待输入>
条件判断
中括号
你可以使用[ 命题 ]
来做一个判断,如果命题是真就会返回真,否则返回假,例如[ $a == 1 ]
注意[ 命题 ]
,命题左右这两个奇怪的空格是不能省略的.
如果命题里面有字符串变量,那么就要在变量两边加双引号,例如[ "$string1" == "asd" ]
短路和断路
类似C语言,语句1||语句2
这样形式的代码,如果语句1返回结果为真,语句2就不会被执行.如果语句1返回假,那么语句2就会被执行.
同样的,语句1&&语句2
这样形式的代码,如果语句1返回结果为假,语句2就不会被执行.如果语句1返回真,那么语句2就会被执行.
你骚一点的话,可以用这个特性来实现if else
.比如这样,判断输入的数字是不是1
.
#!/bin/bash
read -p "please input a integer 1: " a
[ $a == 1 ] && echo "a is 1" || echo "a is not 1"
再比如这样,判断输入的字符串是否一致:
#!/bin/bash
echo "please input two string"
read -p "first string: " firststr
read -p "second string: " secondstr
[ "$firststr" == "$secondstr" ] && echo "equal" || echo "not equal"
if语句
不骚的操作是怎么样的.
尝龟的写法如下:
if [ 命题 ]; then
语句块1
elif [ 命题 ];then
语句块2
else
语句块3
fi
你没有看错,就是这么奇怪,[ 命题 ]
后面要加一个;
,结尾就是fi
.当然elif
是可选的,就像其他语言一样.
例如,判断用户输入的是yes
还是no
还是其他的什么玩意.可以这样写:
#!/bin/bash
read -p "please input yes or no: " value
if [ "$value" == "yes" ]; then
echo "your input string is yes"
elif [ "$value" == "no" ]; then
echo "your input string is no"
else
echo "your input string is unknow"
fi
case语句
通常写法如下:
case $a in
值1)
语句块
;;
值2)
语句块
;;
esac
你还是没有看错,他又是奇怪地在语句块后面加两个分号,奇怪地在值后面加一个括号.
你应该看出来了,这个结束的关键字就是case
倒过来写.
如果是字符串,值应该加个双引号.
例如,你要判断输入的数字是不是1
或者2
或者其他什么玩意:
#!/bin/bash
read a
case $a in
1)
echo "apple"
;;
2)
echo "banana"
;;
*)
echo "unknown"
;;
esac
再例如,你要判断第一个命令行参数是不是a
或者b
或者其他什么玩意:
#!/bin/bash
case $1 in
"a")
echo "apple"
;;
"b")
echo "banana"
;;
*)
echo "unknown"
;;
esac
你应该发现了,*
是什么玩意?
他其实是一个通配符,前面都不符合就会落在他的手上.注意,就算变量是字符串,你也不应该给他加上双引号.
循环
第一种for循环
for 循环变量 in 值1 值2 ... 值n
do
语句
done
这样的话,循环变量会依次被赋值成对应循环次数的值,然后执行循环,直到遍历完所有值.
有点像其他语言的foreach
.例如,用循环输出所有命令行参数(你应该还记得$@
是什么东西吧):
#!/bin/bash
for var in $@
do
echo "var is $var"
done
echo "for stop"
第二种for循环
这是世俗眼光里的for
循环.
for ((循环变量=0; 循环变量<=限制; 循环变量=下一次的循环变量))
do
语句
while
又变得奇怪了,这里要加两个括号的.
例如这样,计算1到n之间每个数字的和:
#!/bin/bash
read -p "please input the n:" n
s=0
for ((i=0; i<=n; i=i+1))
do
s=$(($s+$i))
done
echo "1+2+3...+$n=$s"
函数
没有参数的时候
函数可以写成这样
function 函数名称(){
语句块
}
你也可以省略function
,直接写成
函数名称(){
}
例如,我们通过第一个命令行参数来调用函数:
#!/bin/bash
function help(){
echo "this is first function."
}
function close(){
echo "this is second function."
}
case $1 in
"-1")
help
;;
"-2")
close
;;
*)
echo "nothing happen"
;;
esac
没错,调用的时候只要写函数名称
,而不是函数名称()
.
那就离谱了,参数要写在哪里?
有参数的时候
给函数传参数的方法有点像命令行给程序传参数:
函数名称 参数1 参数2 ... 参数n
那么函数怎么拿到参数?
方法和拿命令行参数一样,例如:
function 函数名称(){
echo $1
}
例如,我们用一个函数来计算1-n之间的数字的和:
#!/bin/bash
function getsum(){
s=0
for ((i=0; i<=$1; i=i+1))
do
s=$(($s+$i))
done
echo "1+2+3...+$1=$s"
}
read -p "please input the num: " n
getsum n
你学会了
你学会了吗,学会了请把学会了
打在公屏上.