Bash浅谈
一、Bash简介
1.What’s Bash
- Bash 是 Unix 系统和 Linux 系统的一种 Shell(命令行环境),是目前绝大多数 Linux 发行版的默认 Shell。
- that’s all.
二、脚本常识
1.声明Bash Shell
#!/bin/bash:声明使用的解析器,可避免系统采用默认解析器去运行脚本带来的可能的错误。Attention:
①第一行的“井号+感叹号+脚本解释器程序路径”,说明这是一个可执行的脚本;
②任意行的单独的”井号“都是注释作用,非第一行的“井号+感叹号“也是注释作用;
③避免问题:你的脚本是Bash Shell,系统默认的是Csh,若不声明,那么你的脚本运行错误;
2.脚本的执行权限
- Linux脚本 不以 后缀来判断它是否可执行,而是以命令 ”ls -l“ 来查看它是否是可执行文件,可使用chmod来变更脚本权限(该命令使用方式请自查文档),这样才能运行;
3.脚本的组织方式
- 脚本是由命令组成的,而命令的执行都是单独的,即使报错也不影响下一条命令的执行;一行语句可以包含多个命令,用”;”隔开。
三、命令基础理解
1.echo命令
echo "xxx" "xxx" …… "xxx"ORecho xxx …… xxx:单行输出;echo "xxx":xxx为多行文本时可以一次输出多行;echo -n "xxx";echo "yyy":可以实现输出xxxyyy,即-n可以省略换行符;- echo -e “damn\nbro”:若没有参数
-e,则转义换行字符\n不会翻译;
2.命令的继发关系
command1 ;command2:无论命令1是否成功执行,都会继续执行命令2;command1 && command2:只有命令1成功执行,命令2才会执行;command1 || command2:只有命令1执行失败,命令2才会执行;
3.type命令
type command:查看command是内部命令还是外部程序;type -a command:显示command的所有定义;type -t command:返回command的类型:别名(alias),关键词(keyword),函数(function),内置命令(builtin)和文件(file);
四、命令的模式拓展(通配符拓展)
1.~拓展
~会自动拓展成当前用户的主目录;~+会自动拓展当前所在目录;
2.?拓展
?字符代表当前目录(不包括子目录)下里面的任意单个字符,不包括空字符;?字符扩展属于文件名扩展,只有文件确实存在的前提下,才会发生扩展。如果文件不存在,扩展就不会发生。
3.拓展*
*字符代表当前目录(不包括子目录)下文件路径里面的任意数量的任意字符,包括空字符。- 如果要匹配隐藏文件,需要写成
.*,否则不会匹配; *字符扩展属于文件名扩展,只有文件确实存在的前提下才会扩展。如果文件不存在,就会原样输出。
4.[ ]拓展
[xyz]代表当前目录(不包括子目录)下文件路径里面的xyz中的任意一个字符。[^xyz]或者[!xyz]代表当前目录(不包括子目录)下文件路径里面的除了xyz以外的任意一个字符。[a-c]等同于[abc],[!a-c]等同于[!abc];- [ ]扩展扩展属于文件名扩展,只有文件确实存在的前提下才会扩展。如果文件不存在,就会原样输出。
5.{ }拓展
- 大括号扩展
{1,2,3}表示分别扩展成大括号里面的所有值,各个值之间使用逗号分隔; - 大括号拓展可以嵌套,也可以与其他模式联用,并且总是先于其他模式进行扩展;
{1..4}等同于{1,2,3,4},{4..1}等同于{4,3,2,1},{01..4}等同于{01,02,03,04},{0..8..2}等同于{0,2,4,6,8};- 大括号扩展不是文件名扩展。它会扩展成所有给定的值,而不管是否有对应的文件存在。当对应文件不存在时,相应命令会报错或者继续通配输出;
6.变量拓展
- 将美元符号
$开头的词元视为变量,将其扩展成变量值; - 变量名除了放在美元符号后面,也可以放在
${}里面; ${!string*}或${!string@}返回所有匹配给定字符串string的变量名;
7.子命令拓展
$(command)可以扩展成另一个命令的运行结果,该命令command的所有输出都会作为返回值。
8.算术拓展
$((...))可以扩展成整数运算的结果:echo $((2 + 2))输出4;
9.字符类拓展
[[:class:]]表示一个字符类,扩展成某一类特定字符之中的一个;- 常见的字符类如下:
[[:alnum:]]:匹配任意英文字母与数字;[[:alpha:]]:匹配任意英文字母;[[:graph:]]:A-Z、a-z、0-9 和标点符号;[[:lower:]]:匹配任意小写字母 a-z;[[:upper:]]:匹配任意大写字母 A-Z;[[:print:]]:ASCII 码 32-127 的可打印字符;[[:cntrl:]]:ASCII 码 0-31 的不可打印字符;[[:digit:]]:匹配任意数字 0-9;[[:xdigit:]]:16进制字符(A-F、a-f、0-9);
- 字符类的第一个方括号后面,可以加上感叹号
!(或^),表示否定。比如,[![:digit:]](或[^[:digit:]])匹配所有非数字。 - 字符类也属于文件名扩展,如果没有匹配的文件名,字符类就会原样输出。
10.Cautions
- 通配符是先解释再执行;
- 所有文件名扩展只匹配单层路径,不能跨目录匹配,即无法匹配子目录里面的文件。或者说,
?或*这样的通配符,不能匹配路径分隔符(/); - Bash 允许文件名使用通配符,即文件名包括特殊字符。这时引用文件名,需要把文件名放在单引号或双引号里面。
五、变量
1.创建变量
- 命令格式:
xxx=value;Attention:
①由字母、数字和下划线组成;
②不能以数字开头;
③赋值时等号两边不能有空格;
④变量的值包含空格则需放入引号中;
⑤Bash没有数据类型的概念,所有变量值都是字符串;
2.读取变量
常用命令格式:
$A或者${A};Attention:
①当变量不存在时,不会报错,而是会输出空字符;
②后者比前者用途更广,比如当变量名与其他字符连用时:${A}damn会输出M3damn,而#Adamn会去尝试读取变量Adamn而输出空字符(A=M3);特殊命令格式:
${!A}可以输出变量的最终值M3(A=DAMN;DAMN=M3);"${A}"可以完整地输出变量值中的所有空格:echo ${A}会输出1 2 3;echo "${A}"会输出1 2 3(A="1 2 3");
3.删除变量
- 命令格式:
unset AA=''A=Attention:因为不存在的 Bash 变量一律等于空字符串,所以即使
unset命令删除了变量,还是可以读取这个变量,值为空字符串。所以,删除一个变量,也可以将这个变量设成空字符串。
4.变量继承
- 命令格式:
export A=damn;Attention:上面命令执行后,当前
shell和随后新建的shell都可以读取变量A,并且子shell修改的变量不会影响父shell;
5.特殊变量
$?:$?为上一个命令的退出码,用来判断上一个命令是否执行成功。返回值是0,表示上一个命令执行成功;如果不是零,表示上一个命令执行失败;- $$$$:$$$$为当前 Shell 的进程 ID;
$_:$_为上一个命令的最后一个参数;$!:$!为最近一个后台执行的异步命令的进程 ID;$0:$0为当前 Shell 的名称(在命令行直接执行时)或者脚本名(在脚本中执行时);$-:$-为当前 Shell 的启动参数;
6.变量的默认值
${A:-damn}:如果变量A存在且不为空,则返回它的值,否则返回damn。它的目的是返回一个默认值;${A:=damn}:如果变量A存在且不为空,则返回它的值,否则将它设为damn,并且返回damn。它的目的是设置变量的默认值;${A:+damn}:如果变量A存在且不为空,则返回damn,否则返回空值。它的目的是测试变量是否存在;${A:?damn}:如果变量A存在且不为空,则返回它的值,否则打印出A: damn,并中断脚本的执行。如果省略了damn,则输出默认的信息“parameter null or not set.”。它的目的是防止变量未定义;- 上面四种语法如果用在脚本中,变量名的部分可以用数字
1到9,表示脚本的参数。
7.declare命令
- 语法格式:
declare -option A=value:declare命令可以声明一些特殊类型的变量,为变量设置一些限制,比如声明只读类型的变量和整数类型的变量。 declare命令如果用在函数中,声明的变量只在函数内部有效,等同于local命令;- 不带任何参数时,
declare命令输出当前环境的所有变量,包括函数在内,等同于不带有任何参数的set命令。-i:-i参数声明整数变量以后,可以直接进行数学运算;-x:-x参数等同于export命令,可以输出一个变量为子 Shell 的环境变量;-r:-r参数可以声明只读变量,无法改变变量值,也不能unset变量;-u:-u参数声明变量为大写字母,可以自动把变量值转成大写字母;-l:-l参数声明变量为小写字母,可以自动把变量值转成小写字母;-p:-p参数输出变量信息;-f:-f参数输出当前环境的所有函数,包括它的定义;-F:-F参数输出当前环境的所有函数名,不包含函数定义;
8.readonly命令
readonly命令等同于declare -r,用来声明只读变量,不能改变变量值,也不能unset变量;
9.let命令
let命令声明变量时,可以直接执行算术表达式;let命令的参数表达式如果包含空格,就需要使用引号;let可以同时对多个变量赋值,赋值表达式之间使用空格分隔;
六、字符串操作
1.字符串的长度
- `$