第一部分 bash简介
在介绍bash之前,需要先介绍它的起源——shell。shell俗称壳,它是指UNIX系统下的一个命令解析器;主要用于用户和系统的交互。UNIX系统上有很多种Shell。首个shell,即Bourne Shell,于1978年在V7(AT&T的第7版)UNIX上推出。后来,又演变出C shell、bash等不同版本的shell。
bash,全称为Bourne-Again Shell。它是一个为GNU项目编写的Unix shell。bash脚本功能非常强大,尤其是在处理自动循环或大的任务方面可节省大量的时间。bash是许多Linux平台的内定Shell,这也是我们介绍它主要的原因。
1 新建文件test.sh
$ touch test.sh
2 添加可执行权限
$ chmod +x test.sh
3 编辑test.sh,test.sh内容如下:
#!/bin/bash echo "hello bash" exit 0
说明:
#!/bin/bash : 它是bash文件声明语句,表示是以/bin/bash程序执行该文件。它必须写在文件的第一行!
echo "hello bash" : 表示在终端输出“hello bash”
exit 0 : 表示返回0。在bash中,0表示执行成功,其他表示失败。
4 执行bash脚本
$ ./bash
在终端输出“bash hello”
条件判断有2中格式,分别是“test EXPRESSION”和“[ EXPRESSION ]”。
“test”判断语句,在实际中应用的比较少;相反的,“[]”判断语句应用很广。下面分别对它们进行介绍
基本格式
test EXPRESSION
格式说明
test是关键字,表示判断;
EXPRESSION是被判断的语句。
关于EXPRESSION的说明,参考如下:
应用实例
一、判断文件/home/skywang/123.txt是不是文件
$ test -f /home/skywang/123.txt
其他说明
在linux系统下,可以通过以下命令去测试上面的实例
# 切换到执行目录(如切换到/home/skywang)
$ cd /home/skywang
# 判断123.txt是不是文件
$ test -f 123.txt
# 输出判断结果,0表示成功,其他表示失败。
# 其中,echo表示输出文本到当前终端,$?表示上一命令的执行结果(在linux中bash中,命令成功返回0,失败返回其他)。
$ echo $?
基本格式
[ EXPRESSION ]
格式说明
中括号的左右扩弧和EXPRESSION之间都必须有空格!
关于EXPRESSION的说明,参考如下:
应用实例
一、判断文件/home/skywang/123.txt是否存在
$ [ -f /home/skywang/123.txt ]
二、判断变量val是否等于字符串“skywang”
$ [ "$val" = "skywang" ]
三,判断变量num是否等于数字100
$ [ "$num" -eq "100" ]
基本格式
-a : 逻辑与,操作符两边均为真,结果为真,否则为假。
-o : 逻辑或,操作符两边一边为真,结果为真,否则为假。
! : 逻辑否,条件为假,结果为真。
应用实例
一、判断文件123.txt是不是可读写
$ [ -r 123.txt -a -w 123.txt ]
等价于
$ [ -r 123.txt ] && [ -w 123.txt ]
二、判断变量num是不是等于数字101或102
$ [ "$num" -eq "101" -o "$num" -eq "102" ]
等价于
$ [ -r 123.txt ] || [ -w 123.txt ]
三、判断文件123.txt是不是不可读
$ [ ! -r 123.txt ]
基本格式
if 条件1
then 命令1
elif 条件2
then 命令2
else 命令3
if
格式说明
if 语句必须以单词 fi 终止。elif 和 else 为可选项,如果语句中没有否则部分,那么就不需要 elif 和 else 部分。if 语句可以有许多 elif 部分。最常用的 if 语句是 if then fi 结构。
应用实例
一、判断文件文件123.txt是否存在,存在则输出“file exist”;没有则输出“file not exist”。bash文件内容如下:
#!/bin/bash if [ -f 123.txt ];then echo "file exist" else echo "file not exist" fi exit 0
二、提示用户输入值。若输入的值小于0,则输出“negtive number”;若等于0,则输出“number zero”,否则,输出“positive number”。bash文件内容如下:
#!/bin/bash # 提示用户输入一个值 echo -n "please input a number:" # 保存用户输入的值到num中 read num if [ "$num" -lt "0" ];then # 小于0,则输出“negtive number” echo "negtive number" elif [ "$num" -gt "0" ];then # 大于0,则输出“positive number” echo "positive number" else # 大于0,则输出"number zero" echo "number zero" fi exit 0
case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
基本格式
case 值 in
模式1}
命令1
...
;;
模式2)
命令2
...
;;
esac
格式说明
“模式”部分可能包括元字符,即:
* 任意字符。
? 任意单字符。
[..] 类或范围中任意字符
应用实例
一、提示用户输入Y/y或N/n。若输入Y/y,则输出“yes”;若输入N/n,则输出“no”;否则,“incorrect input”。bash文件内容如下:
#!/bin/bash # 提示用户输入一个值 echo -n "are you femail(Y/N):" # 保存用户输入的值到val中 read val case $val in Y|y) # 用户输入Y或y echo "yes" ;; N|n) # 用户输入N或n "no" ;; *) # 其它输入 echo "incorrect input" ;; esac exit 0
基本格式
for 变量名in列表
do
命令1
命令2...
done
格式说明
当变量值在列表里, for循环即执行一次所有命令,使用变量名访问列表中取值。命令可为任何有效的 shell命令和语句。变量名为任何单词。 in列表用法是可选的,如果不用它, for循环使用命
令行的位置参数。
应用实例
一、输入当前文件夹的一级子目录中文件名字。bash脚本内容如下:
#!/bin/bash # 将ls的结果保存到变量CUR_DIR中 CUR_DIR=`ls` # 显示ls的结果 echo $CUR_DIR for val in $CUR_DIR do # 若val是文件,则输出该文件名 if [ -f $val ];then echo "FILE: $val" fi done exit 0
二、输出1-10之间数字的总和。bash脚本内容如下:
#!/bin/bash sum=0 for ((i=1;i<10;i++)) do ((sum=$sum+$i)) done echo "sum=$sum" exit 0
until循环执行一系列命令直至条件为真时停止。until循环与 while循环在处理方式上刚好相反。一般 while循环优于until循环,但在某些时候 — 也只是极少数情况下, until循环更加有用。
基本格式
until 条件
命令1
...
done
格式说明
条件可为任意测试条件,测试发生在循环末尾,因此循环至少执行一次 — 请注意这一点。
应用实例
一、从0开始逐步递增,当数值等于5时,停止递增。Bash脚本内容如下:
#!/bin/bash # 设置起始值为0 val=0 until [ "$val" -eq "5" ] do # 输出数值 echo "val=$val" # 将数值加1 ((val++)) done exit 0
基本格式
while 命令
do
命令1
命令2
...
done
应用实例
一、从0开始逐步递增,当数值等于5时,停止递增。Bash脚本内容如下:
#!/bin/bash # 设置起始值为0 val=0 while [ "$val" -lt "5" ] do # 输出数值 echo "val=$val" # 将数值加1 ((val++)) done exit 0
基本格式
break命令允许跳出循环。
continue命令类似于 break命令,只有一点重要差别,它不会跳出循环,只是跳过这个循环步。
应用实例
一、[break应用]从0开始逐步递增,当数值等于5时,停止递增。Bash脚本内容如下:
#!/bin/bash # 设置起始值为0 val=0 while true do if [ "$val" -eq "5" ];then # 如果val=5,则跳出循环 break; else # 输出数值 echo "val=$val" # 将数值加1 ((val++)) fi done exit 0
二、[continue应用]从0开始逐步递增到10:当数值为5时,将数值递增2;否则,输出数值。Bash脚本内容如下:
#!/bin/bash # 设置起始值为0 val=0 while [ "$val" -le "10" ] do if [ "$val" -eq "5" ];then # 如果val=5,则将数值加2 ((val=$val+2)) continue; else # 输出数值 echo "val=$val" # 将数值加1 ((val++)) fi done exit 0
第四部分 bash数组
array=(10 20 30 40 50)
一对括号表示是数组,数组元素用“空格”符号分割开。引用数组时从序号0开始。
除了上面的定义方式外,也可以单独定义数组:
array[0]=10
array[1]=20
array[2]=30
array[3]=40
array[4]=50
(01) 显示数组中第2项
$ echo ${array[i]} 说明:数组是从序号0开始计算(即第1项为array[0])。
(02) 显示数组中的所有元素
$ echo ${array[@]} 或者 $ echo ${array[*]}
(03) 显示数组长度
$ echo ${#array[@]} 或者 $ echo ${#array[*]}
(04) 删除数组第2项元素
$ unset array[1] 说明: unset仅仅只清除array[1]的值,并没有将array[1]删除掉
(05) 删除整个数组
$ unset array
(06) 输出数组的第1-3项
$ echo ${array[@]:0:3} 说明: 参考“${数组名[@或*]:起始位置:长度}”
(07) 将数组中的0替换成1
$ echo ${a[@]/0/1} 说明: ${数组名[@或*]/查找字符/替换字符
第五部分 函数
基本格式
function 函数名()
{
...
}
格式说明
function可有可无。但建议保留,因为保留的话看起来更加直观。
应用实例
function foo() { # 定义局部变量i local i=0 # 定义局部变量total=传入foo的参数总数 local total=$# # 输出参数总数 echo "total param =$total" # 输出传入foo的每一个参数 for val in $@ do ((i++)) echo "$i -- val=$val" done # 返回参数总数 return $total }
调用方法
直接通过函数名去调用。
应用实例
foo param1 param2 param3
说明:
调用函数foo,并传入param1 param2 param3三个参数
使用方法
return 返回值
方法说明
例如,foo param1 param2 param3之后,再调用$?就是上次调用的返回值
编辑一个函数foo:打印foo的输入参数的总数,并输入每个参数和参数对应的序号。
#!/bin/bash function foo() { # 定义局部变量i local i=0 # 定义局部变量total=传入foo的参数总数 local total=$# # 输出参数总数 echo "total param =$total" # 输出传入foo的每一个参数 for val in $@ do ((i++)) echo "$i -- val=$val" done # 返回参数总数 return $total } foo foo param1 param2 param3 # 输出foo param1 param2 param3的返回值 echo "return value=$?" exit 0
输出结果:
total param =0 total param =3 1 -- val=param1 2 -- val=param2 3 -- val=param3 return value=3
第六部分 数值运算
数值比较请参考"第三部分"的1.2节,本部分只介绍数值运算。
常用的4种数值运算说明
数值元算主要有4种实现方式:(())、let、expr、bc。
工作效率:
(()) == let > expr > bc
(01), (())和let是bash内建命令,执行效率高;而expr和bc是系统命令,会消耗内存,执行效率低。
(02), (())、let和expr只支持整数运算,不支持浮点运算;而bc支持浮点运算。
下面分别介绍这4种实现方式的使用方法。
应用实例一:分别用上面四种方式实现"3*(5+2)"。
#!/bin/bash # 数值i=3*(5+2) (方法一:$(())实现) val=$((3*(5+2))) echo "val=$val" # 数值i=3*(5+2) (方法二:let实现) let "val=3*(5+2)" echo "val=$val" # 数值i=3*(5+2) (方法三:expr实现) val=`expr 3 \* \( 5 + 2 \)` echo "val=$val" # 数值i=3*(5+2) (方法四:bc实现) val=`echo "3*(5+2)"|bc` echo "val=$val" exit 0
应用实例二:分别勇上面四种方式实现“数值+1”。
#!/bin/bash val=0 # 数值加1 (方法一) ((val++)) echo "val=$val" val=0 # 数值加1 (方法二) let val++ echo "val=$val" val=0 # 数值加1 (方法三) val=`expr $val + 1` echo "val=$val" val=0 # 数值加1(方法四) val=`echo "$val+1"|bc` echo "val=$val" exit 0
应用实例三:计算1/3,保留3位小数。
#!/bin/bash # 数值i=3*(5+2) (方法四:bc实现) val=`echo "scale=3; 1/3"|bc` echo "val=$val" exit 0
第七部分 字符运算
首先,我们定义个str字符串变量,然后再对此变量进行字符串操作。
$ str="hello world"
(01) 显示字符串长度
$ echo ${#str}
(02) 提取world
$ echo ${str:6}
(03) 提取or
$ echo ${str:7:2}
(04) 删除hello
$ echo ${str#hello} 或 $ echo ${str#*lo}
(05) 删除world
$ echo ${str%world} 或 $ echo ${str%wo*}
(06) 将所有的字符“l”替换为“m”
$ echo ${str//l/m}
第八部分 bash自带参数
第九部分 bash调试
bash [-nvx] scripts.sh
选项与参数:
-n :不要执行 script,仅查询语法的问题;
-v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;
-x :将使用到的 script 内容显示到屏幕上,这是很有用的参数!
例如,想要执行bash脚本,并查看bash的调用流程,可以通过以下命令:
$ bash -x test.sh
2 echo调试
echo [OPTION] STRING
-n : 输出内容之后,不换行。默认是输入内容之后,换行。
-e : 开启反斜线“\”转义功能
-E : 开启反斜线“\”转义功能(默认)。
例如,输出“please input a number:”之后不换行。
$ echo -n "please input a number:"
3 printf
和echo一样,printf也能用于输出。语法格式和C语言中printf一样。
例如,输出“hello printf”之后换行。
$ printf "hello printf\n"
第十部分 bash注释
# echo "single line"
说明:#放在文件开头,表示注释掉本行。
可以通过以下两种方法实现多行注释:
:||{ ....被注释的多行内容 }
或者
if false ; then ....被注释的多行内容 fi
第十一部分 bash内建指令
基本格式
type cmd
格式说明
type是命令关键字,cmd表示查看的命令;若输出builtin,则该命令是bash的内建命令。
例如:
$ type echo
除此之外,用户也可以通过man bash或者man builtins查看bash的全部内置命令.
(01)echo
命令:echo arg
功能:在屏幕上显示出由arg指定的字串
(02)read
命令格式:read变量名表
功能:从标准输入设备读入一行,分解成若干字,赋值给bash程序内部定义的变量
(03)shift
命令:shift [N] (N为大于0的整数;当N省略时,等价与于“shift 1”)
功能:所有的参数依次向左移动N个位置,并使用$#减少N,直到$#=0为止。
(04)alias
命令:alias name='value'
功能:别名。用name替换value,value要用单引号括住。
(05)export
命令:export变量名[=变量值]
功能:export可以把bash的变量向下带入子bash(即子bash中可以使用父bash的变量),从而让子进程继承父进程中的环境变量。但子bash不能用export把它的变量向上带入父bash。
(06)readonly
命令:readonly 变量名
功能:定义只读变量。不带任何参数的readonly命令将显示出所有只读变量。
(07)exec
命令:exec 命令参数
功能:当bash执行到exec语句时,不会去创建新的子进程,而是转去执行指定的命令,当指定的命令执行完时,该进程(也就是最初的bash)就终止了,所以bash程序中exec后面的语句将不再
被执行。
(08)"."(点)
命令:. bash程序文件名
功能:使bash读入指定的bash程序文件并依次执行文件中的所有语句。
(09)exit
命令:exit N
功能:退出Shell程序。在exit之后可有选择地指定一个数位作为返回状态。
http://www.haogongju.net/art/2054684