高级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,求最大公约数

 

posted @ 2017-10-27 23:02  哨音  阅读(408)  评论(0编辑  收藏  举报