《Linux Shell脚本攻略》学习笔记-第一章

1.1 简介

计算机可以从文本文件(称为shell脚本)中读取并执行命令。

sehll脚本不仅节省了时间,而且清楚明白地表明了所执行的操作。

bash shell变成了UNIXLinux中既成事实的标准shell

1.2 在终端中显示输出

1)

$表示普通用户,#表示管理员用户root

推荐使用普通用户登录系统,然后借助sudo这类工具来运行特权命令,其执行命令的效果和root一样。

《Linux Shell脚本攻略》学习笔记-第一章_第1张图片

2)

shell脚本通常以shebang起始。

#!/bin/bash

其中#!位于解释器路径之前;/bin/bash是bash的解释器命令路径。

脚本中只有第一行可以使用shebang来定义解释该脚本所使用的解释器。

脚本执行的两种方式:

bash 文件名.sh

chmod 755 文件名.sh

./文件名.sh

如果将脚本作为bash的命令行参数来运行,那么就不需要使用shebang了。

内核会读取脚本的首行并注意到shebang为#!/bin/bash,他会识别出/bin/bash并执行该脚本。

3)

~表示主目录,通常为/home/user,其中uesr是用户名。

$cmd1 ; cmd2 等同于$cmd1 $cmd2

《Linux Shell脚本攻略》学习笔记-第一章_第2张图片

4)

ehco是用于终端打印的最基本命令,默认情况下,echo在每次调用后会添加一个换行符。可以使用-n来禁止echo在文本的末尾追加换行符。

《Linux Shell脚本攻略》学习笔记-第一章_第3张图片

双引号允许shell解释字符串中出现的特殊字符,单引号不会对其做任何解释。

在使用转义序列时,需要使用echo -e“包含转义序列的字符串”这种形式。

打印彩色文本输出

5)

printf命令接受 引用文本或由空格分隔的参数。我们可以在printf中使用格式化字符串来指定字符串的宽度、左右对齐方式等。

默认情况下,printf并不会自动添加换行符。

《Linux Shell脚本攻略》学习笔记-第一章_第4张图片

%s,%c,%d,%f都是格式替换符,它们定义了该如何打印后续参数。

6)

文本颜色:0,30-37

彩色背景:0,40-47

《Linux Shell脚本攻略》学习笔记-第一章_第5张图片

 

1.3 使用变量与环境变量

和编译型语言不同,大多数脚本语言不要求在创建变量之前声明其类型,在变量名前面加上一个美元符号就可以访问到变量的值。

常用的惯例是在脚本中使用大写字母命名环境变量,使用驼峰命名法或者小写字母命名其他变量。

1)查看全部环境变量

使用env或者printenv命令查看当前shell中所定义的全部环境变量。

《Linux Shell脚本攻略》学习笔记-第一章_第6张图片

查看其他进程的环境变量,其中PID是相关进程的进程ID;使用pgrep命令获取进程ID。

《Linux Shell脚本攻略》学习笔记-第一章_第7张图片

2)

     var = value:等号两边加上空格,表示的是等量测试关系。

     var=value:等号两边没有空格,是赋值操作符。

3)

因为shell使用空白字符来分隔单词,所以我们需要加上一对花括号来告诉shell这里的变量名是fruit,而不是fruits。

《Linux Shell脚本攻略》学习笔记-第一章_第8张图片

4)

使用单引号时,变量不会被扩展,仍旧照原样显示;使用双引号就会显示出变量的值,如果没有定义过,则什么都不显示。

《Linux Shell脚本攻略》学习笔记-第一章_第9张图片

5)

《Linux Shell脚本攻略》学习笔记-第一章_第10张图片

环境变量UID中保存的是用户ID。它可以用于检查当前脚本时以root用户还是以普通用户的身份运行的。

root用户的UID0

《Linux Shell脚本攻略》学习笔记-第一章_第11张图片

1.4 使用函数添加环境变量

这个例子展示了如何将新的路径添加到环境变量的起始部分。

《Linux Shell脚本攻略》学习笔记-第一章_第12张图片

[ -d "$2" ]:判断第二个函数指定的目录是否存在

如果存在eval表达式将第一个参数所指定的变量值设置成第二个参数的值加上:,随后再跟上第一个参数的原始值。

${parameter:+expression}:如果parameter有值且不为空,则使用expression的值。

1.5 使用shell进行数学运算

bash shell使用let、(( ))和[ ]执行基本的算术操作。

工具expr和bc可以用来执行高级操作。

1)let命令可以用来直接执行基本的算术操作。当使用let时,变量名之前不需要再添加$。

《Linux Shell脚本攻略》学习笔记-第一章_第13张图片

2)操作符[]的使用方法和let命令一样;也可以在[]中使用$前缀。

《Linux Shell脚本攻略》学习笔记-第一章_第14张图片

3)也可以使用操作符(( )),出现在(( ))中的变量名之前需要加上$

《Linux Shell脚本攻略》学习笔记-第一章_第15张图片

4)expr命令也可以执行基本算术操作,算术符号的前后一定要有空格

《Linux Shell脚本攻略》学习笔记-第一章_第16张图片

以上这些方法只能用于整数运算,不支持浮点数。

5)bc是一种用于数学运算的高级使用工具,可以借助它执行读点书运算并使用一些高级函数。

《Linux Shell脚本攻略》学习笔记-第一章_第17张图片

《Linux Shell脚本攻略》学习笔记-第一章_第18张图片

根据在线手册,bc对于加减乘三种算法依据输入中的最高精度来确定输出精度,不会进行自行截断,此时scale设置无效。解决方法可以使用printf来控制输出精度;但是除法则相反,可以通过设置scale来设置精度。

《Linux Shell脚本攻略》学习笔记-第一章_第19张图片

《Linux Shell脚本攻略》学习笔记-第一章_第20张图片

其中obase是转换后的进制,ibase是转换前的进制

《Linux Shell脚本攻略》学习笔记-第一章_第21张图片

1.6 玩转文件描述符与重定向

文件描述符是与输入和输出流相关联的整数。最广为人知的文件描述符是stdin、stdout和stderr。

脚本可以使用大于号将输出重定向到文件中。命令产生的文本可能是正常输出,也可能是错误信息。

正常输出和错误信息都会显示在屏幕上,我们可以分别为其指定特定的文件描述符来区分两者。

0

stdin 标准输入

1

stdout 标准输出

2

stderr 标准错误

《Linux Shell脚本攻略》学习笔记-第一章_第22张图片

其中命令成功执行后退出状态为0,发生错误会返回一个非0的退出状态。

标准错误一般不会重定向到文件中

方法:

《Linux Shell脚本攻略》学习笔记-第一章_第23张图片

stdout作为单数据流,可以被重定向到文件或是通过管道传入其他程序,但是两者无法兼得。

有一种方法tee既可以将数据重定向到文件,又可以提供一份重定向数据的副本作为管道中后续命令的stdin。

《Linux Shell脚本攻略》学习笔记-第一章_第24张图片

默认情况下,tee命令将文件覆盖,但是它提供了一个-a选项,可用于追加内容。

《Linux Shell脚本攻略》学习笔记-第一章_第25张图片

借助小于号,我们可以像使用stdin一样从文件中读取数据。

《Linux Shell脚本攻略》学习笔记-第一章_第26张图片

《Linux Shell脚本攻略》学习笔记-第一章_第27张图片

出现在cat <<_EOF_ > cat.txt与下一行_EOF_之间的所有文本行都会被当做stdin数据。

cat.txt文件的内容显示如下:

exec命令创建全新的文件描述符。<操作符可以将文件读入stdin;>操作符用于截断模式的文件写入;>>操作符用于追加模式的文件写入。

《Linux Shell脚本攻略》学习笔记-第一章_第28张图片

1.7 数组与关联数组

bash支持普通数组和关联数组,前者使用整数作为数组索引,后者使用字符串作为数组索引。

《Linux Shell脚本攻略》学习笔记-第一章_第29张图片

《Linux Shell脚本攻略》学习笔记-第一章_第30张图片

《Linux Shell脚本攻略》学习笔记-第一章_第31张图片

《Linux Shell脚本攻略》学习笔记-第一章_第32张图片

《Linux Shell脚本攻略》学习笔记-第一章_第33张图片

1.8 别名

别名是一种便捷方式,可以为用户省去输入一长串命令序列的麻烦。

《Linux Shell脚本攻略》学习笔记-第一章_第34张图片

《Linux Shell脚本攻略》学习笔记-第一章_第35张图片

《Linux Shell脚本攻略》学习笔记-第一章_第36张图片

字符\可以转义命令,从而执行原本的命令。在不可信的环境下执行特权命令时,在命令前加上\来忽略可能存在的别名总是一种良好的安全实践。

1.9  采集中断信息

tput和stty是两款终端处理工具。

《Linux Shell脚本攻略》学习笔记-第一章_第37张图片

《Linux Shell脚本攻略》学习笔记-第一章_第38张图片

《Linux Shell脚本攻略》学习笔记-第一章_第39张图片

《Linux Shell脚本攻略》学习笔记-第一章_第40张图片

stty命令的选项-echo禁止将输出发送到终端,而选项echo则允许发送输出。

1.10 获取并设置日期及延时

在系统内部,日期被存储成一个整数,其取值为从1970年1月1日0时0分0秒起所流逝的秒数。这种纪元方式称为纪元时或者Unix时间。

《Linux Shell脚本攻略》学习笔记-第一章_第41张图片

《Linux Shell脚本攻略》学习笔记-第一章_第42张图片

《Linux Shell脚本攻略》学习笔记-第一章_第43张图片

《Linux Shell脚本攻略》学习笔记-第一章_第44张图片

sleep命令可以延迟脚本执行一段时间,以秒为单位。

《Linux Shell脚本攻略》学习笔记-第一章_第45张图片

1.11 调试脚本

《Linux Shell脚本攻略》学习笔记-第一章_第46张图片

运行带有-x选项的脚本可以打印出所执行的每一行命令及当前状态。

《Linux Shell脚本攻略》学习笔记-第一章_第47张图片

set -x

在执行时显示参数和命令

set +x

禁止调试

set -v

当命令进行读取时显示输入

set +v

禁止打印输入

《Linux Shell脚本攻略》学习笔记-第一章_第48张图片

《Linux Shell脚本攻略》学习笔记-第一章_第49张图片

export PS4='$LINENO:',调试时显示每行的行号。

调试时使用-x或者set -x选项,调试输出会被发送到stderr。

1.12 函数和参数

最大的差异在于函数参数可以在函数体中任意位置上使用,而别名只能将参数放在命令尾部。

《Linux Shell脚本攻略》学习笔记-第一章_第50张图片

$0是脚本名称,$n是第n个参数,"$@"被扩展成"$1""$2""$3""$*"被扩展成"$1c$2c$3",其中cIFS的第一个字符。

函数也能像环境变量一样使用export导出,如此一来函数的作用域就可以扩展到子进程中。

《Linux Shell脚本攻略》学习笔记-第一章_第51张图片

《Linux Shell脚本攻略》学习笔记-第一章_第52张图片

《Linux Shell脚本攻略》学习笔记-第一章_第53张图片

1.13 将一个命令的输出发送给另一个命令

一个命令的输出可以作为另一个命令的输入,而这个命令的输出又会传递至下一个命令,以此类推。

我们使用管道连接每个过滤器,管道的操作符是 | 。

cmd1的输出传递给cmd2,cmd2的输出传递给cmd3,最终的输出会出现在显示器中或者被导入某个文件。

《Linux Shell脚本攻略》学习笔记-第一章_第54张图片

子shell是一个独立的进程,可以使用()操作符来定义一个子shell。

《Linux Shell脚本攻略》学习笔记-第一章_第55张图片

当命令在子shell中执行时,不会对当前shell造成任何影响;所有的改变仅限于该子shell内。

假设我们使用子shell或者反引号的方法将命令中的输出保存到变量中,为了保留输出的空格和换行符,必须使用双引号。(存疑)

《Linux Shell脚本攻略》学习笔记-第一章_第56张图片

1.14 在不按下回车键的情况下连续读入n个字符

bash中的read命令能够从键盘或者标准输入中读取文本。编程语言的大多数输入库都是从键盘读取输入,当回车键按下的时候标志着输入完毕。

但有时候没发按回车键,输入结束与否是由读取到的字符数或某个特定字符来决定的。

《Linux Shell脚本攻略》学习笔记-第一章_第57张图片

read -t有其特殊性,结束后会自动在命令行中显示输入的值;若是接下来还有read,可能将其作为一种输入。

1.15 持续运行命令直至执行成功

《Linux Shell脚本攻略》学习笔记-第一章_第58张图片

该循环执行以函数参数形式$@传入的命令。如果命令执行成功,则返回,进而退出循环。

true是作为/bin中的一个二进制文件来实现的。这意味着每执行一次之前提到的while循环,shell就不得不生成一个进程。

为了避免这种情况,可以使用shell的内建命令:,该命令的退出状态总是0。

《Linux Shell脚本攻略》学习笔记-第一章_第59张图片

《Linux Shell脚本攻略》学习笔记-第一章_第60张图片

1.16 字段分隔符与迭代器

内部字段分隔符(IFS)是shell脚本中的一个重要概念。IFS是一个环境变量,其中保存了用于分隔的字符,它是当前shell环境使用的默认定界字符串。

IFS的默认值是空白字符(换行符、制表符或者空格)

《Linux Shell脚本攻略》学习笔记-第一章_第61张图片

《Linux Shell脚本攻略》学习笔记-第一章_第62张图片

《Linux Shell脚本攻略》学习笔记-第一章_第63张图片

《Linux Shell脚本攻略》学习笔记-第一章_第64张图片

当条件为真时,while循环继续执行;当循环条件为假时,until循环继续执行。

用true作为循环条件可以产生无线循环。

1.17 比较与测试

程序中的流程控制是由比较语句和测试语句处理的。我们可以使用if、if else以及逻辑运算符来测试,用比较运算符来比较数据项。

除此之外,还有一个test命令可以用于测试。

《Linux Shell脚本攻略》学习笔记-第一章_第65张图片

&&:如果condition为真,则执行action

||:如果condition为假,则执行action

《Linux Shell脚本攻略》学习笔记-第一章_第66张图片

一定要注意运算符、比较复[ ]与操作数之间的空格,否则可能达不到想要的效果,或者报错。

《Linux Shell脚本攻略》学习笔记-第一章_第67张图片

-a-o放在[[ ]]中会报错

我们可以使用不同的条件标志测试各文件系统的相关属性。

《Linux Shell脚本攻略》学习笔记-第一章_第68张图片

《Linux Shell脚本攻略》学习笔记-第一章_第69张图片

根据ASCII值进行比较。

《Linux Shell脚本攻略》学习笔记-第一章_第70张图片

使用test命令可以避免使用过多的括号,增强代码的可读性。

但是test命令的执行效率要低于括号,因为test是外部程序,而括号是内建命令。

《Linux Shell脚本攻略》学习笔记-第一章_第71张图片

解决方法:

《Linux Shell脚本攻略》学习笔记-第一章_第72张图片

《Linux Shell脚本攻略》学习笔记-第一章_第73张图片

1.18 使用配置文件定制bash

Linux中能够放置定制脚本的文件不止一个。这些配置文件分为三类:登录时执行的、启动交互式shell时执行的、调用shell处理脚本文件时执行的。

  • test命令
  • 字符串比较
  • 文件系统相关测试
  • 算术比较
  • 逻辑与、逻辑或
  • if、if else使用方法
  • 循环
  • 实战练习
  • 改变默认IFS
  • 加入延时sleep
  • 一种更快的做法
  • 通过子shell的方式保留空格和换行符
  • 利用子shell生成一个独立的进程
  • 将命令序列的输出赋值给变量
  • 管道
  • shift命令可以将参数依次向左移动一个位置,让脚本能够使用$1来访问每一个参数。
  • 读取命令的返回值
  • 递归函数:在bash中,函数同样支持递归调用(可以调用自身的函数)
  • 导出函数
  • 函数参数可以按照位置访问。
  • 函数定义和执行的方式
  • 补充知识
  • 使用set -v和set +v可以对脚本输入进行部分调试
  • 使用set -x和set +x可以对脚本进行部分调试
  • bash -x:启用shell脚本的跟踪调试功能
  • 在脚本中加入延时
  • date命令所支持的格式选项
  • 计算一段shell脚本所使用的的执行时间
  • 常用日期命令
  • stty
  • tput
  • 转义字符 \
  • 查看当前环境中定义的所有别名
  • alias命令的效果只是暂时的。一旦关闭终端,所有设置过的别名都会失效。想要使别名在所有的shell中都可用,可以将其定义为放入~/.bashrc文件中。
  • 删除别名:只需要将对应的定义从~/.bashrc文件中删除,或者使用unalias命令,也可以使用alias 别名=。
  • 创建别名:alias
  • 关联数组:当使用字符串作为索引时,关联数组要比数字索引数组更容易使用。
  • 打印数组的长度
  • 以列表形式打印出所有的值
  • 打印出特定索引的数组元素内容
  • 定义数组的方法
  • 自定义文件描述符
  • 重定向脚本内部的文本块
  • 将文件重定向到命令
  • 标准错误重定向
  • 在命令行结束后立即执行echo $?,就可以打印出退出状态。
  • 使用大于号将文本保存到文件中,使用双大于号将文本追加到文件中。
  • 计算平方及平方根
  • 进制转换
  • 设定小数精度:
  • 检查当前用户是否为超级用户
  • 识别当前所使用的的shell:$SHELL或者$0
  • 获取字符串长度:${#变量名}

你可能感兴趣的:(Shell脚本攻略,linux,学习,bash)