shell脚本学习笔记
shell脚本的格式
shell脚本默认文件扩展名为.sh
。在shell脚本中,你写入的内容,会默认当成一条命令来执行。
例如:
#!/bin/bash echo 'hello world'
- 第1行 指定shell脚本的默认解释器
- 第2行 执行echo命令
将上面的代码存为test.sh,并将可执行权限赋予它chmod +x test.sh
,执行./test.sh
运行脚本。
上面的脚本将会输出:
hello world
注释
和所有的编程语言一样,shell也有注释,在shell中,#号和它后面的内容来表示一个注释:
# print a message echo "i'm a shell script."
输出内容
echo用于向输出流输出内容,例如:
echo "hello world"
输入内容
read关键字用于输入一条内容:
read input echo $input
上面的代码中,read关键字从输入流读取一个值并赋予input,然后将input的内容打印出来
1. 变量
定义变量和赋值
变量的命名规则和c语言差不多,支持英文字母和下划线。shell中变量名前不需要声明类型,变量名后面不能有空格,例如:
var1='hello' var2=90
读取变量
$后接变量名意为读取一个变量的值,例如:
var="hello" echo $var
也可以用${var}
方式访问到变量值,例如:
var="hello" echo ${var}
访问变量的时候
$var
和${var}
是等效的,推荐后者来访问一个变量
变量作用域
全局变量
没有任何关键字修饰的变量是一个全局变量,全局变量在同一个shell会话中都是有效的。可以跨文件
function func(){ a=90 } func echo $a
输出:
90
$ a=90 $ echo ${a} $ bash $ echo ${a}
输出:
90
空值
局部变量
local关键字用于声明一个局部变量
function func(){ local a=90 } func echo $a
输出:
空值
环境变量
用export关键字修饰的变量称为环境变量,在父shell会话中声明一个环境变量,子shell中都可以访问
$ export path="/system/bin" $ bash #创建一个新的shell会话 $ echo ${path}
特殊变量
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n(n≥1) | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2 |
$# | 传递给脚本或函数的参数个数 |
$* | 传递给脚本或函数的所有参数 |
$@ | 传递给脚本或函数的所有参数 |
$? | 上个命令的退出状态,或函数的返回值 |
$$ | 当前 shell 进程 id。对于 shell 脚本,就是这些脚本所在的进程 id |
$*和$@的区别
- $*得到所有参数的字符串形式
- $@得到所有参数的数组形式,可以直接遍历
2. 获取一条命令的执行结果
用 ` 将一条命令包裹起来
` 这个符号,在键盘上的位置是在esc键的下方
ret=${pwd} echo ${ret}
在 ` 包裹起来的命令中,也可以访问到变量
path='/' ret=`ls -l ${path}` echo ${ret}
以$(command)这种方式执行命令
ret=$(pwd) echo ${ret}
用$(command)这种方式也可以访问到变量
path='/' ret=$(ls -l ${path}) echo ${ret}
上面的例子中,如果想打印命令结果中的换行符,则:
path='/' ret=$(ls -l ${path}) echo "${ret}"
$(command)方式来执行命令更加直观,但是要注意,$() 仅在 bash shell 中有效,而反引号可在多种 shell 中都可使用
3. 字符串
shell有三种方式可以表示字符串
字符串的表示
(1)变量名后直接跟上字符
str=hello echo ${str}
输出:
hello
这种方式的字符串遇到空格,$等分隔符就会被终止
(2)单引号
str=hello echo '${str}'
输出:
${str}
单引号里的内容是字符串原始的样子,不存在转义
(3)双引号
str=shell echo "${str}:\"hello wolrd\""
输出:
shell:"hello world"
双引号中可以访问变量和转义
字符串的长度
str="hello" echo ${#str}
字符串拼接
两个变量放在一起访问就可以拼接
a='hello' b='world' c=${a}${b} echo ${c}
输出:
helloworld
字符串截取
(1) 从左边开始截取字符串,格式:${string: start :length}
,length可省略,省略时,是截取到字符串末尾
msg="hello world" echo ${msg: 6: 5}
输出:
world
(2) 在指定位置截取字符
- 截取chars后面的字符:
${string#*chars}
其中,string 表示要截取的字符,chars 是指定的字符(或者子字符串),是通配符的一种,表示任意长度的字符串。chars连起来使用的意思是:忽略左边的所有字符,直到遇见 chars(chars 不会被截取)。
截取最后一次出现chars的位置后面的内容:
${string##*chars}
使用 % 截取左边字符
使用%号可以截取指定字符(或者子字符串)左边的所有字符,具体格式如下:
${string%chars*}
请注意 * 的位置,因为要截取 chars 左边的字符,而忽略 chars 右边的字符,所以 * 应该位于chars的右侧。其他方面%和#的用法相同
4. 运算符和流程控制
基本运算
运算符 | 作用 |
---|---|
+ | 加(需要结合expr命令使用) |
- | 减(需要结合expr命令使用) |
* | 乘(需要结合expr命令使用) |
/ | 除(需要结合expr命令使用) |
% | 求余(需要结合expr命令使用) |
= | 赋值 |
== | 判断数值是否相等,需要结合[] 使用 |
!= | 判断数值是否不相等,需要结合[] 使用 |
a=8 b=4 echo "a=$a,b=$b" var=`expr ${a} + ${b}` echo "加法结果:${var}" var=`expr ${a} - ${b}` echo "减法结果:${var}" # 注意:乘号需要转义 var=`expr ${a} \* ${b}` echo "乘法结果:${var}" var=`expr ${a} / ${b}` echo "除法结果:${var}" var=`expr ${a} % ${b}` echo "求余结果:${var}" var=$[${a} == ${b}] echo "是否相等:${var}" var=$[${a} != ${b}] echo "是否不相等:${var}"
输出:
a=8,b=4 加法结果:12 减法结果:4 乘法结果:32 除法结果:2 求余结果:0 是否相等:0 是否不相等:1
上面的例子中,调用expr命令和使用[]
,得到表达式的值,并将它们输出
请注意表达式两边的空格,shell中表达式两边要有空格
关系运算
运算符 | 作用 |
---|---|
-eq | 全称:equal,判断两个数是否相等 |
-ne | 全称:not equal,判断两个数是否不相等 |
-gt | 全称:greater than,判断前面那个数是否大于后面那个数 |
-lt | 全称:less than,判断前面那个数是否小于后面那个数 |
-ge | 全称:greater equal,判断前面那个数是否大于等于后面那个数 |
-le | 全称:less than,判断前面那个数是否小于等于后面那个数 |
布尔运算
运算符 | 作用 |
---|---|
! | 非运算 |
-o | 或运算 |
-a | 并运算 |
逻辑运算
运算符 | 作用 |
---|---|
&& | 逻辑并 |
| |
逻辑或 |
文件判断
运算符 | 作用 |
---|---|
-e | 判断对象是否存在 |
-d | 判断对象是否存在,并且为目录 |
-f | 判断对象是否存在,并且为常规文件 |
-l | 判断对象是否存在,并且为符号链接 |
-h | 判断对象是否存在,并且为软链接 |
-s | 判断对象是否存在,并且长度不为0 |
-r | 判断对象是否存在,并且可读 |
-w | 判断对象是否存在,并且可写 |
-x | 判断对象是否存在,并且可执行 |
-o | 判断对象是否存在,并且属于当前用户 |
-g | 判断对象是否存在,并且属于当前用户组 |
-nt | 判断file1是否比file2新 |
-ot | 判断file1是否比file2旧 |
流程控制语句
(1) if语句
if语句格式如下:
if [ <condition> ] then #do something elif [ <condition> ] then #do something else #do something fi
如果想把then和if放同一行
if [ <condition> ] ; then #do something elif [ <condition> ] ; then #do something else #do something fi
其中elif和else可以省略
例子:
read file if [ -f ${file} ] ; then echo 'this is normal file.' elif [ -d ${file} ] ; then echo 'this is dir' elif [ -c ${file} -o -b ${file} ] ; then echo 'this is device file.' else echo 'this is unknown file.' fi
逻辑判断也可以用test命令,它和[]
的作用是一样的
a=4 b=4 if test $[a+2] -eq $[b+2] then echo "表达式结果相等" else echo "表达式结果不相等" fi
输出:
表达式结果不相等
(2) for 语句
if语句格式如下:
for [ <var> ] in [list] do # do something done
例子:
read input for val in ${input} ; do echo "val:${val}" done
输入:
1 2 3 4 5
输出:
val:1
val:2
val:3
val:4
val:5
(3) while 语句
while [ <condition> ] do #do something done
例子:
a=1 sum=0 while [ ${a} -le 100 ] ;do sum=`expr ${sum} + ${a}` a=`expr ${a} + 1` done echo ${sum}
输出:
5050
5. 函数
- 用function关键字来定义一个函数
- 直接写一个函数名来调用一个无参数的函数
- 函数有参数,调用时,在函数名后面写上参数,多个参数用空格隔开
- 调用函数时传递参数,在函数体内部,通过 $n的形式来获取参数的值,例如:$1表示第1个参数,$2表示第2个参数...
函数的结构
function foo(){ # do everything... }
函数的用法示例
function foo(){ local name=$1 local age=$2 echo "my name is: ${name},i'm ${age} years old." } foo "luoye" 26
输出:
my name is: luoye,i'm 26 years old.
6. 参考
http://c.biancheng.net/shell/
http://www.runoob.com/linux/linux-shell-process-control.html
https://www.cnblogs.com/qlqwjy/p/8684630.html
上一篇: 第81节:Java中的数组
下一篇: Ubuntu常用终端命令—重启与关机