Shell脚本攻略(1)—-小试牛刀

1.1简介
命令提示符中,‘$’表示普通用户,’#’表示超级用户。shell脚本通常是以“#!”其实的文本文件。其中“#!”称为shebang,在执行脚本时,shell程序会读取脚本的首行,查看shebang行是否为“#! /bin/bash”。它会识别/bin/bash,并在内部以如下命令执行

当打开一个终端时,该终端就会执行一遍~/.bashrc。在bash中,每个命令或命令序列是通过使用换行符来分隔的。
1.2终端打印
如下三种都可以完成同样的输出结果,echo在每次调用后会输出一个换行符(使用 -n 可以忽略掉此换行符):

但各有一些特殊的用途和副作用。
比如双引号中存在‘!’,就必须对其转义,单引号中的$var或被当作常量打印,不带引号的中间不能使用‘;’等等。
另一个可用于终端打印的事printf,使用方法类似于c语言中的printf函数
注意:echo和printf中的标志(-e,-n等)必须出现在命令行内任何字符串之前,如:

补充:
(1)使用双引号内的转义序列:

(2)打印彩色:

1.3变量与环境变量
脚本语言通常不需要在使用之前声明其类型,并且在Bash中,无论你给变量赋值时是否加引号,每一个变量的值都是字符串。环境变量是一类特殊的变量,它用于Shell环境和操作系统环境存储一些特殊的值。
env命令查看所有与此终端进程有关的环境变量。每个进程运行时的环境变量使用下面命令查询:

变量的赋值:

打印:

在双引号中引用变量值:

输出如下:
We have 5 apple(s)
环境变量是未在当前进程中定义,而从父进程中继承而来的变量。export命令用来设置环境变量。

补充:
(1)获得字符串长度:

(2)识别当前shell版本

(3)检查是否为超级用户

(4)修改Bash提示字符串

\u用户名,\hz主机名,\w工作目录
1.4通过shell进行数学运算
在Bash shell中可以利用let、(())、[]进行基本的算数操作,使用expr和bc进行一些高级操作。

以上这些不支持浮点运算。下面开始浮点运算:

补充
(1)设置小数精度

(2)进制转换

(3)平方与平方根

1.5文件描述符与重定向
将输出重定向到一个文件中

当一个命令发生错误并退出时,会返回一个非0的退出状态,退出状态可以通过 echo $?查看

如果不想在终端显示stderr的任何内容,可以使用/dev/null,/deb/null是一个特殊的设备文件,这个文件接收的任何文件都会被丢弃,null文件通常被称为位桶(bit bucket)或黑洞。

下面的代码中,tee命令接收来自stdin的数据。它将stdout的一份副本写入文件out.txt,同时将另一份副本作为后续命名的stdin。命令cat -n将从stdin中接收到的每一行数据前加上行号并写入stdout(注意tee只能从stdin中进行读取,不能读取stderr):

我们可以使用stdin作为命令参数,只需要使用-作为命令的文件名参数即可:

类似的,我们可以使用/dev/stdin作为输出文件名来使用stdin
补充
(1)将文件重定向到命令

(2)重定向脚本内部的文本块
向log文件中写入头信息:

之后,cat <<EOF>log.txt到下一个EOF中间的内容将作为stdin数据。
(3)自定义文件描述符

我们可以这样使用它:

创建一个文件描述符用于追加:

1.6数组和关联数组
Bash支持普通数组和关联数组,普通数组只能使用整数作为数组索引,而关联数组(Bash4.0开始支持)可以使用字符串作为数组索引。
定义数组:

打印数组元素:

打印数组中的所有值

打印数组长度

补充
(1)定义关联数组

(2)列出数组索引

1.7使用别名
创建一个别名

为了使别名一直起作用,可以将它放入~/.bashrc中。

删除alias:删除~/.bashrc中对应语句或使用unalias

另一种创建别名的方法是定义一个具有新名称的函数,并把它写入 ~/.bashrc

补充
有时我们不希望使用别名,通过字符’\’对命令进行转义,这就使得我们可以执行用来的命令,而不是别名替身。
1.8获取终端信息
tput和stty事两款终端处理工具。

输入密码时,不让输入的内容显示出来

1.9获取设置日期和延时

纪元时被定义为从世界标准时间1970年1月1日0时0分0秒到现在时间的总秒数,不包括润秒。
将日期串转化为纪元时

日期格式字符串列表:
星期:%a(Sta),%A(Staurday)
月:%b(Nov).%B(November)
日:%d(31)
固定格式日期:%D(10/18/10)
年:%y(10),%Y(2010)
小时:%I,%H(08)
分钟:%M(33)
秒:%S(10)
纳秒:%N(695208515)
UNIX纪元时(秒为单位):%s(1290049486)

检查一组命令所花费的时间

补充
在脚本中延时

1.10调试脚本

以自定义格式显示调试信息_DEBUG

补充
用shebang进行调试:

1.11函数和参数
定义函数

补充
(1)递归函数

(2)导出函数

(3)读取命令返回值

(4)向命令传递参数
假设-p、-v是可用选项,-k NO事另一个可以接受数字的选项,同时该命令还接受一个文件名作为参数,那么,它有以下几种执行方式:

1.12读取命令序列输出

另一种被称为子shell(subshell)的方法也可以用于存储命令输出

反引用‘`’位于键盘的~键上
补充
(1)利用子shell生成一个独立的进程
子shell本身就是独立的进程,使用()操作符来定义一个子shell

在子shel中执行时,不会对当前shell有任何影响
(2)通过引用子shell的方式保留空格和换行符
假设我们使用子shell或反引用的方法将命令的输出读入一个变量中,可以将它放入双引号中,以保留空格和换行符(\n)

1.13以不按回车键的方式读取字符“n”
read命令提供了一种不需要按回车键就能够搞定这个任务的方法。

1.14字段分隔符和迭代器
内部字段分隔符(Internal Field Separator,IFS)
CSV(Comma Separator Value),逗号分隔型数值

IFS的默认值为空白符(换行符、制表符或空格)
/etc/password中,每一行包含了由冒号划分的多个条目,类似如下形式:
root:x:0:0:root:/root:/bin/bash

bash中的循环:

1.15 比较与测试

-gt:大于
-lt:小于
-ge:大于或等于
-le:小于或等于

文件系统相关测试:
[ -f $file_var ]:file_var是否包含正常的文件路径或文件名
[ -x $var ]:var包含的文件是否可执行
[ -d $var ]:是否是目录
[ -e $var ]:文件是否存在
[ -c $var ]:是否是字符设备文件路径
[ -b $var ]:是否是块设备文件路径
[ -w $var ]:是否可写
[ -r $var ]:是否可读
[ -L $var ]:是否是一个符号链接
字符串比较
进行字符串比较时,最好使用双中括号。
[[ $str1 = $str2 ]]:是否相等,注意“=”两边的空格
[[ $str1 == $str2 ]]:是否相等的另一种写法
[[ $str1 != $str2 ]]:是否不等
[[ $str1 > $str2 ]]:str1的字母序大于str2
[[ $str1 < $str2 ]]:str1的字母序小于str2
[[ -z $str1 ]]:是否为空
[[ -n $str2 ]]:是否非空

0 条评论
发表一条评论

注意: 评论者允许使用'@user空格'的方式将自己的评论通知另外评论者。例如, ABC是本文的评论者之一,则使用'@ABC '(不包括单引号)将会自动将您的评论发送给ABC。使用'@all ',将会将评论发送给之前所有其它评论者。请务必注意user必须和评论者名相匹配(大小写一致)。