高级BASH
Bash介绍与入门
1,简介
Bash(GNU Bourne-Again Shell)是一个为GNU计划编写的Unix shell,它是许多Linux平台默认使用的shell
shell是一个命令解释器,是结余操作系统内核与用户之间的一个绝缘层。
2,为什么学Bash
对于任何想适当精通一下系统管理知识的人来说,掌握shell脚步知识都是最基本的。
3,初步练习
(1)Hello World
(2)使用脚步清除/var/log下的log文件
查看/var/log下的log文件,并创建新的脚本
代码:
实验机有点差别,有权限,不给删除
Bash的特殊字符(上)
一、#符号
1.#注释
行首以#开头(除#!之外)的是注释。#!是用于指定当前脚本的解释器,我们这里为bash,且应该指明完整路径,所以为/bin/bash
代码:
结果:
二、分号(;)
1.命令分隔符
使用分号(;)可以在同一行上写两个或两个以上的命令
输入代码:
执行脚本:
2.终止case选项(双分号)
使用双分号(;;)可以终止case选项
输入代码
执行脚本:
上面脚本使用case语句,首先创建了一个变量初始化为b,然后使用case语句判断该变量的范围,并打印相关信息。
三,点号(.)
1.等价于source命令
bash中的source命令用于当前bash环境下读取并执行FileName.sh中的命令
四,引号
1,双引号(“)
“STRING”将阻止(解释)STRING中大部分特殊的字符。
2,单引号(‘)
’STRING‘将会阻止STRING中所有特殊字符的解释,这是一种比使用“更强烈的形式。
五,斜线和反斜线
1,斜线(/)
文件名路径分隔符。分隔文件名不同的部分
(如/home/bozo/projects/Makefile)。也可以用来作为除法算数操作符
2,反斜线(\)
一种对单字符的引用机制。\X将会“转义”字符X。这等价于“X",也等价于'X'。\通常用来转义双引号(“)和单引号(’),这样双引号和单引号就不会被解释成特殊含义
六,反引号(`)
1,命令替换
command结构可以将命令的输出赋值到一个变量中去。在后边的后置引用(backquotes)或后置标记(backticks)中也会讲解。
反引号中的命令会优先执行,如:
先创建了back目录,然后赋值test.sh到back目录
七,冒号(:)
1,空命令
等价于“NOP”(no op,一个什么也不干的命令)。也可以被认为与shell的内建命令true作业相同。“:”命令是一个bash的内建命令,它的退出码(exit status)是(0)。
如
等价于
可以在if/then中作占位符
2.变量扩展/子串
在与>重定向操作符结合使用时,将会把一个文件清空,但是并不会修改这个文件的权限。如果之前这个文件并不存在,那么就创建这个文件。
在与>>重定向操作符结合使用时,将不会对预先存在的目标文件(:>>target_file)产生任何影响。如果这个文件之前并不存在,那么就创建它。
也可能用来作为注释行,但不推荐这么做。使用#来注释的话,将关闭剩余行的错误检查,所以可以在注释行中写任何东西。然而,使用的话将不会这样做。如:
“:”还用来在/etc/passwd和¥PATH变量中做分隔符,如:
八,问号(?)
1,测试操作符
在一个双括号结果中,?就是C语言的三元操作符,如:
代码:
运行测试:
九,美元符号
1,变量替换
命令:
测试运行:
2,命令替换(同反引号)
Bash中的特殊字符(下)
一,小括号(())
1,命令组
在括号中的命令列表,将会作为一个子shell来运行
在括号中的变量,由于是在子shell中,所以对于脚本剩下的部分是不可用的。父进程,也就是脚本本身,将不能够读取在子进程中创建的变量,也就是在子shell中创建的变量。如:
运行代码
在圆括号中a变量,更像是一个局部变量
2,初始化数组
创建数组
输入代码:
运行结果
二,大括号
1,文件名扩展
复制t.txt的内容到t.back中
注意:大括号中,不允许有空白,除非这个空白被应用或转义。
2,代码块
代码块,又被称为内部组,这个结果事实上创建了一个匿名函数(一个没有名字的函数)。然而,与“标准”函数不同的是,在其中声明的变量,对于脚本其他部分的代码来说还是说可见的。
三,中括号([])
1,条件测试
条件测试表达式在[ ]中。值得注意的是[是shell内建test命令的一部分,并不是/usr/bin/test中的外部命令的一个链接。下列练习中的-lt(less than)表示小于号
双中括号中([[ ]])也用作条件测试(判断)
2,数组元素
在一个array结构的上下文中,中括号用来引用数组中每个元素的编号
四,尖括号(<和>)
1,重定向
test.sh > filename重定向test.sh的输出到文件filename中。如果filename存在的话,那么将会被覆盖。
test.sh &> filename重定向test.sh的stdout(标志输出)和stderr(标准错误)到filename中
test.sh >&2重定向到test.sh的stdout到stderr中
test.sh >> filename把test.sh的输出追加到文件filename中。如果filename不存在的话,将会被创建。
五,竖线(| )
管道
分析前边命令的输出,并将输出作为后边命令的输入。这是一种产生命令链的好方法
输出的内容均变为了大写字母
六,破折号( - )
1,选项,前缀
在所有的命令内如果想使用选项参数的话,前边都要加上“-”
2,用于重定向stdin或stdout
下面的脚本用于备份最后24小时当前目录下所有修改的文件
七,波浪号(~)
1,目录
~表示home目录
变量和参数
一,变量替换
1.概念
变量的名字就是变量保存值得地方。引用变量的值就叫做变量替换。
如果variable是一个变量的名字,那么$variable就是引用这变量的值,即这变量所包含的数据
$variable事实上只是${variable}的简写形式。在某些上下文中$variable可能会引起错误,这时候你就需要用${variable}了。
2.举例
结果:
二,变量赋值
1,说明
赋值操作前后都不能有空白
因为 = 和 -eq 都可以用做条件测试操作,所以不要与这里的赋值操作相混淆
注意:=既可以用做条件测试操作,也可以用于赋值操作,这需要视具体的上下文而定。bash中==也可作为条件判断。
运行结果
三,变量不区分类型
1,说明
与大多数编译型语言不同,Bahs并不区分变量的“类型”。本质上Bash变量都是字符串。但是依赖于具体的上下文,Bahs也允许比较和整数操作。其中的关键因素就是,为变量赋的值是否只有数字
2,举例:
运行结果:
四,特殊变量
1,局部变量
这种变量只有在代码块或函数中才可见。
2,环境变量
这种变量将影响用户接口和shell的行为
在通常情况下,每个进程都有自己的"环境“,这个环境是由一组变量组成的,这些变量中存在进程可能需要引用的信息。在这种情况下,shell与一个一般的进程没什么区别。
3,位置参数
从命令行传递到脚本的参数:$0,$1,$2,$3...
$0就是脚本文件自身的名字,$1是第一个参数,$2是第二个参数,$3是第三个参数,然后是第四个。$9之后的位置参数就必须用大括号括起来了,比如,${10},${11},${12}。
两个比较特殊的变量$*和$@表示所有位置参数
4,位置参数实例
引用和转义
一,引用变量
1,介绍
在一个双引号中通过直接使用变量名的方法来引用变量,一般情况下都是没问题的。这么做将阻止所有在引号中的特殊字符被重新解释(即都被当做普通的字符串),包括变量名,但是$,`(后置引用)和“\"(转义符)除外。
保留$作为特殊字符的意义是为了能够在双引号中也能够正常的引用变量(“$variable")。
使用双引号还能够阻止单词分割,即使这个参数包含空白,单词也不会被分隔开。如variable1="a variable containing five words"
2,举例
在echo语句中,只有在单词分割或者保留空白的时候,才需要把参数用双引号括起来。
运行结果:
IFS(Internal Field Seperator)在Linux的shell中的预设的分隔符。
IFS是shell脚本中的一个重要概念,在处理文本数据时,它是相当有用的。内部字段分隔符是用于特定用途的定界符。IFS是存储定界符的环境变量,它是当前shell环境使用的默认定界字符串
单引号(‘ ’)操作与双引号基本一样,但是不允许引用变量,因为$的特殊意义将被关闭。
在单引号中,任何特殊字符都按照字面的意识进行解释,除了单引号本身。所以说单引号(全引用)是一种比双引号(部分引用)更严格的引用方法
二,转义
1,概念
转义是一种引用单个字符的方法。一个签名放上转义符(\)的字符就是告诉shell这个字符按照字面的意思进行解释,换句话说,就是这个字符失去了它的特殊含义。
2,转义符的含义
在echo命令中:
\$表示$本身字面的含义(跟在\$后边的变量名将不能引用变量的值),如:
\\表示反斜杠线字面的意思,如:
3,一个实例
运行结果
4,转义符(\)的行为探究
\ 的行为依赖于它自身是否被转义,被引用(“”),或者是否会出现在命令替换或here document中。
举例:
运行结果:
5,变量中的转义
赋值给变量的字符串的元素也会被转义,但是不能把一个单独的转义符赋值给变量
6,转义空格
转移一个空格会阻止命令行参数列表的“单词分割”问题
运行结果:
7,续行功能
转义符也提供续行功能,也就是编写多行命令的功能
每个单词行都包含一个不同的命令,但是每行结尾的转义符都会转义换行符,这样下一行会与上一行一起形成一个命令序列。
运行结果:
如果一个脚本以 | (管道符)结束,那么就不同非的加上转义符( \ )了。但是一个好的编程风格,还是应该在行尾加上转义符。
退出和退出状态码
一,退出状态码
1,退出
exit被用来结束一个脚本,它返回一个值,并且这个值会传递给脚本的父进程,父进程会使用一个值做下一步的处理。
2,退出状态码
每个命令都会返回一个退出状态码(有时候也被称为返回状态)。
成功的命令放回0,不成功的命令放回非零值,非零值通常都被解释成一个错误码。行为良好的UNIX命令、程序和工具都会返回0作为退出码来表示成功,虽然偶尔也会有例外。
同样的,脚本中的函数和脚本本身也会返回退出状态码。在脚本或者是脚本函数中执行的最后的命令会决定退出状态码。在脚本中,exit nnn命令将会nnn退出码递给shell(nnn必须是十进制数,范围必须是0-255)
当脚本以不带参数的exit命令来结束时,脚本的退出状态码就由脚本中最后执行的命令来决定(就是exit之前的命令)。
3,一个例子
$?指代的是上一条指令的执行结果
不带参数的exit命令与exit $? 的效果是一样的,甚至脚本的结尾不写exit也与前两者的效果相同。
二,反转一个条件的用法
1,例子
! 逻辑 “非”操作符,将会反转命令或条件测试的结果,并且这会影响退出状态码。
运行结果:
特定的退出状态码具有保留含义,所以用户不应该在脚本中指定它。
条件判断
一,条件测试结构
1,if/then结构
if/then结构用来判断命令列表的退出状态符是否为0,0表示成功,如果成功的话,就执行接下来的一个或多个命令
注意:这里与C语言等其他语言不同,不能直接使用0或者1作为判断条件,而应该以false,true代替。与其他大多数语言相反的true返回的是0,false返回的是1.
有一个专有命令 [ (左中括号,特殊字符),这个命令与test命令等价,由于效率上的考虑,bash将它作为一个内建命令。
注意:由于Bash的语法检查机制的原因,如果在条件测试时只使用一个[会出现一个错误提示,为了避免这个问题,我们通常将使用一对方括号包含条件测试[]
在版本2.02的Bash中,引入了“[[...]]”扩展测试命令,[[是一个关键字,并不是一个命令。
if命令能够测试任何命令,并不仅仅是中括号中的条件。
2,多级比较(应注意与嵌套条件分支区分)
运行结果:
注意:((...))和let..如果运算结果为非0,该语句退出码为0,否则为1;[[...]]是作为一个单独的语句并且会返回一个退出码
3,真假判断
4,(( ))结构
(( )) 结构扩展并计算一个算术表达式的值。如果表达式的结果为0,那么返回的退出状态符为1,或者是“假”。而一个非零值得表达式所返回的退出状态码为0,或者是“true”。
二,文件测试操作符
1,操作符列举
举例:
三,二元比较操作符
1,整数比较
-eq 等于
if [ "$a" -eq "$b" ]
-ne 不等于
if [ "$a" -ne "$b"]
-gt 大于
if [ "$a -gt "$b"]
-ge 大于等于
if [ "$a" -ge "$b"]
-lt 小于
if [ "$a -lt "$b" ]
-le 小于等于
if [ "$a -le "$b"]
< 小于(在双括号中使用)
(( "$a" < " $b"))
<=小于等于(在双括号中使用)
(( "$a" <= "$b"))
> (在双括号中使用)
(( "$a > "$b" ))
=>(在双括号中使用)
(( "$a" => "$b"))
2,字符串比较
=等于
if [ "$a" = "$b"]
= =等于, 与= 等价
if [ "$a" == "$b" ]
< 小于,按照ASCII字符进行排序
if [ "$a" < "$b"]]
if [ "$a" \< "$b"]]
注意“<”使用在[]结构中的时候需要被转义
大于,按照ASCII字符进行排序
if [[ "$a" > "$b" ]]
if [[ "$a" \> “$b"]]
-z字符串为“null”,意思就是字符串长度为零-n字符串不为“null"
3,算术比较与字符串比较
4,检查字符串是否为null
运行结果:
5,zmore
6.compound和comparison
-a逻辑与exp1 -a exp2 如果表达式exp1和exp2都为真的话那么结果为真。
-o逻辑或exp1 -o exp2 如果表达式exp1和exp2中至少有一个为真的话,那么结果为真。
注意:这与Bash中的比较操作符&&和||非常相像,但是这两个操作符是用在双中括号中的。
[[ condition1 && condition2 ]]
-o 和 -a 操作符一般都是和test命令或者是单中括号结构一起使用的
if [ "$exp1" -a "exp2" ]
操作符
一,赋值
1,变量赋值
= 通用赋值操作符,可用于算术和字符串赋值。
var=27
vategory=minerals #在“="之后是不允许出现空白字符的。
不要混淆=赋值操作与=测试操作符。也正是因为这一点,在bash里面测试操作也常写作==,但这可能在其他shell中是不允许的
----------------------------------------------------------------------
# = 在这里是测试操作符
if [ "$string1" = "$string2" ]
# if [ "X$string1" = "X$string2" ] 是一种更安全的做法
#这样可以防止两个变量中的一个为空所产生的错误
# ( 字符“X”作为前缀在等式两边是可以互相抵消的。)
then
command
fi
---------------------------------------------------------------------------
二,算术操作符
1,简单算术操作符
2,求最大公约数