Linuxshell脚本(2)

printf命令:

printf是一个把从标准输入的字符按照你所要求的格式输出到标准输出即屏幕的命令. 在很多时候,我们可能需要将自己的数据给他格式化输出的。

1.格式化输出。print  format

2.命令格式:printf'打印格式'实际内容

3.打印格式:

1\a(警告声音输出)

wKiom1lSZqzhQ_t2AAANdu8xjGo678.png

2)\b(退格键)

wKioL1lSZqzyU7WvAAALxgeiXcE510.png

3\f(清除屏幕,类似换纸)

wKioL1lSZqySmbpKAAANY382cq4320.png

4)\n(输出新的一行)

wKiom1lSZq3wTCTYAAAMS0oOXA8677.png

5\r(帧处于行的开始,即enter键)

wKioL1lSZq3BQedWAAAMYp68sWM235.png

6\t(水平的table键)

7)\v(垂直的table键)

wKiom1lSZq6iPJe5AAAMVcyVsgM388.png

8\xNNxASCII码十六进制表示;NN为俩位数数字;可转换数字成为字符)

Linux之shell脚本(2)_第1张图片

9)%nsn为数字;s代表string,即多少个字符)

wKiom1lSZq_RZTAeAAANE3YAWSk263.png

10%nin为数字;i代表integer,即多少整数字符)

wKioL1lSZq_ChAP7AAAP_bb83yE086.png

11%N.nfnN为数字;f代表floating浮点,小数字数即小数点)

Linux之shell脚本(2)_第2张图片

案例:

1)以整数形式输出23并换行,以字符串形式输出hello并换行

wKioL1lSZq_iY30xAAATnKPKE9A167.png

2)2位整数形式输出23并换行,以7位字符串形式输出hello并换行

Linux之shell脚本(2)_第3张图片

案例文本

 

考试分数的输出:假设有一个文件test.txt记录着考试分数,内容如下图所示:

Linux之shell脚本(2)_第4张图片

3下图所示,printf命令的输出结果并没有对齐,%s代表一个不固定长度的字符串,而字符串与字符串中间就以 \t 这个 [tab] 分隔符来处理。既然每个字段的长度不固定会造成上述的困扰,那我将每个字段固定就好啦。

Linux之shell脚本(2)_第5张图片

test.txt文件中的内容,分别以字符串、整数、小数点来显示:

Linux之shell脚本(2)_第6张图片

上面的格式共分为五个字段%10s 代表的是一个长度为 10 个字符的字符串字段,%5i 代表的是长度为 5 个字符的数字字段,至于那个 %8.2f 则代表长度为 8 个字符的具有小数点的字段,其中小数点有两个字符宽度;全部的宽度仅有 8 个字符,整数部分占有 5 个字符,小数点本身 (.) 占一位,小数点后的位数则有两位。 

二、awk命令:

awk也是一个数据处理工具!相较于 sed 常常作用于一整个行的处理, awk 则比较倾向于一行当中分成数个字段来处理。

.awk语言的最基本功能是在文件或字符串中基于指定规则来分解抽取信息,也可以基于指定的规则来输出数据。

有三种方式调用awk

1)命令行方式

awk   [-F  field-separator]  'commands'  input-files

其中,[-F域分隔符]是可选的,因为awk使用空格或tab键作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,如果要浏览诸如passwd文件,此文件各域以冒号作为分隔符,则必须指明-F选项,如:awk -F: 'commands' input-file

:linux系统中用环境变量IFS存储分隔符,但根据实际应用也可以改变IFS的值.

例如:查看默认分隔符。

Linux之shell脚本(2)_第7张图片

注意:oldIFS=$IFS(把环境变量IFS存到oldIFS

Linux之shell脚本(2)_第8张图片

IFS=","(定义分隔符为,

2)shel脚本方式

将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用。

相当于shell脚本首行的:#!/bin/sh可以换成:#!/bin/awk

wKiom1lSZrHSRg63AAAMyWhzb-M304.png

3将所有的awk命令插入一个单独文件,然后调用:

Awk -f awk-script-file input-files

其中,-f选项加载awk-script-file中的awk脚本,input-files跟上面的是一样的。

 

awk的模式和动作

任何awk语句都由模式和动作组成(awk_pattern { actions })。
在一个awk脚本中可能有许多语句。

模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。即省略时不对输入记录进行匹配比较就执行相应的actions。

 

模式可以是任何条件语句或正则表达式等。awk_pattern可以是以下几种类型:

①正则表达式(/regexp/

Linux之shell脚本(2)_第9张图片

布尔表达式用作awk_pattern,表达式成立时,触发相应的actions执行。

1表达式中可以使用变量(如字段变量$1,$2)/regexp/

2布尔表达式中的操作符:

关系操作符: < > <= >= == !=
匹配操作符: value ~ /regexp/ 如果value匹配/regexp/,则返回真
value !~ /regexp/ 如果value不匹配/regexp/,则返回真

3&&() ||() 可以连接两个/regexp/或者布尔表达式,构成混合表达式。!() 可以用于布尔表达式或者/regexp/之前。

例如:提取test.txtchinese大于75为优秀。

Linux之shell脚本(2)_第10张图片

例如:提取passwd中匹配d开头的显示ok

例如:模式包括两个特殊字段 BEGINEND。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。

动作:

实际动作在大括号{ }内指明。动作大多数用来打印,但是还有些更长的代码诸如i f和循环语句及循环退出结构。如果不指明采取动作,awk将打印出所有浏览出来的记录。

awk执行时,其浏览域标记为$1$2...$n。这种方法称为域标识。使用这些域标识将更容易对域进行进一步处理。

 

使用$1 , $3表示参照第1和第3域,注意这里用逗号做域分隔。如果希望打印一个有5个域的记录的所有域,不必指明$1 , $2 , $3 , $4 , $5,可使用$0,意即所有域。为打印一个域或所有域,使用print命令。这是一个awk动作

awk的运行过程:

① 如果BEGIN 区块存在,awk执行它指定的actions。

②  awk从输入文件中读取一行,称为一条输入记录。(如果输入文件省略,将从标准输入读取)

③  awk将读入的记录分割成字段,将第1个字段放入变量$1中,第2个字段放入$2,以此类推。$0表示整条记录。

④  把当前输入记录依次与每一个awk_cmd中awk_pattern比较,看是否匹配,如果相匹配,就执行对应的actions。如果不匹配,就跳过对应的actions,直到比较完所有的awk_cmd。

⑤  当一条输入记录比较了所有的awk_cmd后,awk读取输入的下一行,继续重复步骤,这个过程一直持续,直到awk读取到文件尾。

⑥  awk读完所有的输入行后,如果存在END,就执行相应的actions。

awk入门实例:

1显示/etc/passwd文件中用户名和登录shell

2显示/etc/passwd文件中用户名和登录shell,中间以tab分隔

3:显示/etc/passwd文件中用户名和登录shell,中间以逗号分隔

4:显示/etc/passwd文件中UID大于500的所有用户的用户名和登录shell

5显示/etc/passwd文件中的UID大于500的用户名和登录shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"

Linux之shell脚本(2)_第11张图片

1.awk 后面接两个单引号并加上大括号 {} 来设定想要对数据进行的处理动作

2.awk工作流程是这样的:先执行BEGING,然后读取文件,读入有\n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

六、函数及脚本的综合应用

 

1shell函数:shell允许将一组命令集或语句形成一个可用块,这些块称为shell函数。

 

函数由两部分组成:函数标题、函数体。

 

标题是函数名。函数体是函数内的命令集合。

 

标题名应该唯一;如果不是,将会混淆结果,因为脚本在查看调用脚本前将首先搜索函数调用相应的shell

 

2定义函数的格式为:

函数名(){

命令1

...

}

如果愿意,可在函数名前加上关键字function,这取决于使用者。

function函数名()

{ 

  命令1

  ...

}

例如:

Linux之shell脚本(2)_第12张图片

脚本案例:

案例一、删除文件中的空行:

这个脚本(脚本名为del.lines)可以处理一个或多个文件。每个文件在用sed删除空行之前要先核实是否存在。

sed的输出被导入一个文件名中含有$ $的临时文件,最后这个临时文件又被移回到原来的文件中。

该脚本使用shift命令取得所有的文件名,用while循环逐个处理所有的文件,直至处理完

为止。可以使用del.lines --help获得一个简短的帮助

Linux之shell脚本(2)_第13张图片

chmod  +x  del.lines,增加执行权限,

测试如下:

Linux之shell脚本(2)_第14张图片

注:

1、basename命令能够从路径中分离出文件名。通常用于shell脚本中

2、shift语句用于迁移位置变量,将 $1~$9 依次向左传递

例如,若当前脚本程序获得的位置变量如下:

$1=file1、$2=file2、$3=file3、$4=file4

则执行一次shift命令后,各位置变量为:

$1=file2、$2=file3、$3=file4

再次执行shift命令后,各位置变量为:

$1=file3、$2=file4

案例二、日志文件超过长度,备份,清除内容:

Linux之shell脚本(2)_第15张图片

脚本内容

Linux之shell脚本(2)_第16张图片

注:du 并不是显示文件的实际大小,而是显示文件所占用的 block 大小,默认linux系统分区的 block size 4k,也就是说即使文件只有1个字节,也会占用4k.
ls -l则是文件的实际大小。