AWK详解

一、什么是awk

awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它可在命令行中使用,但更多是作为脚本来使用。awk3个不同版本: awknawkgawk,未作特别说明,一般指gawk

 

二、awk的语法形式及命令选项

1.命令行方式

awk [-F  field-separator]  'awk 脚本'  input-file(s)

其中,’awk 脚本是真正awk命令,必须包含在单引号中,[-F 域分隔符]是可选的, input-file(s) 是待处理的文件。在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指定[-F 域分隔符]的情况下,默认的域分隔符是空格。

 

2.shell脚本方式

将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一般通过键入脚本名称来调用。相当于shell脚本首行的:#!/bin/sh可以换成:#!/bin/awk

 

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

awk -f awk-script-file input-file(s)

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

awk的命令选项:

选项

含义

-F

指定输入文件的分隔符

-f

读取awk脚本文件

-v

赋值自定义变量

 

三、awk的环境变量

变量名称

描述

$n

当前记录的第n个字段,字段间由FS分隔。(列内容)

$0

完整的输入记录。(行内容)

NF

当前记录中的字段数。(列数)

NR

当前记录数。(行数)

FNR

NR,但相对于当前文件。

FS

字段分隔符(默认是任何空格)。(输入列分隔符)

RS

记录分隔符(默认是一个换行符)。(输入行分隔符)

OFS

输出字段分隔符(默认值是一个空格)。(输入列分隔符)

ORS

输出记录分隔符(默认值是一个换行符)。(输出行分隔符)

ARGC

命令行参数的数目。

ARGIND

命令行中当前文件的位置(0开始算)

ARGV

包含命令行参数的数组。

CONVFMT

数字转换格式(默认值为%.6g)

ENVIRON

环境变量关联数组。

ERRNO

最后一个系统错误的描述。

FIELDWIDTHS

字段宽度列表(用空格键分隔)

FILENAME

当前文件名。

IGNORECASE

如果为真,则进行忽略大小写的匹配。

OFMT

数字的输出格式(默认值是%.6g)

RLENGTH

match函数所匹配的字符串的长度。

RSTART

match函数所匹配的字符串的第一个位置。

SUBSEP

数组下标分隔符(默认值是\034)

 

四、awk的运算符

运算符

描述

= += -= *= /= %= ^= **=

赋值

?:

C条件表达式

||

逻辑或

&&

逻辑与

!

逻辑非

~ !~

匹配正则表达式和不匹配正则表达式

< <= > >= != ==

关系运算符

空格

字符串连接

+ -

加,减

* / &

乘,除与求余

^ **

求幂

++ --

增加或减少,作为前缀或后缀

$

域引用

in

数组成员

 

五、gawk专用正则表达式元字符

除了常用的通用元字符集外,以下几个是gawk专用的,不适合unix版本的awk

1/y :匹配一个单词开头或者末尾的空字符串。

2/B:匹配单词内的空字符串。

3/<:匹配一个单词的开头的空字符串,锚定开始。

4/> :匹配一个单词的末尾的空字符串,锚定末尾。

5/w :匹配一个字母数字下划线组成的单词。

6/W :匹配一个非字母数字下划线组成的单词。

7/‘:匹配字符串开头的一个空字符串。

8/' :匹配字符串末尾的一个空字符串。

 

六、POSIX字符集

字符

含义

[:alnum:]

代表英文大小写字符及数字,亦即 0-9, A-Z, a-z

[:alpha:]

代表任何英文大小写字符,亦即 A-Z, a-z

[:lower:]

代表小写字符,亦即 a-z

[:upper:]

代表大写字符,亦即 A-Z

[:digit:]

代表数字而已,亦即 0-9

[:blank:]

代表空白键与 [Tab] 按键两者

[:space:]

任何会产生空白的字符,包括空白键, [Tab], CR 等等

[:cntrl:]

代表键盘上面的控制按键,亦即包括 CR, LF, Tab, Del.. 等等

[:graph:]

除了空白字符 (空白键与 [Tab] 按键) 外的其他所有按键

[:print:]

代表任何可以被列印出来的字符

[:punct:]

代表标点符号 (punctuation symbol),亦即:" ' ? ! ; : # $...

[:xdigit:]

代表 16 进位的数字类型,因此包括: 0-9, A-F, a-f 的数字与字符

 

七、记录和域(行和列)

1 记录

awk把每一个以换行符结束的行称为一个记录。

记录分隔符:默认的输入和输出的分隔符都是回车,保存在内建变量RSORS中。

变量$0:它指的是整条记录。如$ awk '{print $0}' test将输出test文件中的所有记录。

变量NR:一个计数器,每处理完一条记录,NR的值就增加1。如$ awk '{print NR,$0}' test将输出test文件中所有记录,并在记录前显示记录号。

2 

记录中每个单词称做,默认情况下以空格或tab分隔。

变量NF:保存一个记录中域的数量。

3 域分隔符

内建变量FS保存输入域分隔符的值,默认是空格或tab。我们可以通过-F命令行选项修改FS的值。如$ awk -F: '{print $1,$5}' test将打印以冒号为分隔符的第一,第五列的内容。

可以同时使用多个域分隔符,这时应该把分隔符写成放到方括号中,如$awk -F'[:\t]' '{print $1,$3}' test,表示以空格、冒号和tab作为分隔符。

输出域的分隔符默认是一个空格,保存在OFS中。$ awk -F: '{print $1,$5}' test$1$5间的逗号就是OFS的值。

 

八、awk的组成和执行方式

1awk 脚本的组成:

awk 脚本可以由一条或多条awk_cmd组成,两条awk_cmd之间一般以NEWLINE分隔

awk_cmd由两部分组成:pattern { actions }

awk 脚本可以被分成多行书写,必须确保整个awk 脚本被单引号括起来。

2) awk命令的一般形式:

awk ' BEGIN { actions }

pattern1 { actions }

............

patternN { actions }

END { actions }’

input_file [input file]

其中 BEGIN { actions } END { actions } 是可选的。

3) awk的运行过程:

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

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

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

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

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

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

4) input_file可以是多于一个文件的文件列表,awk将按顺序处理列表中的每个文件。

5) 一条awk_cmdpattern可以省略,省略时不对输入记录进行匹配比较就执行相应的actions。一条awk_cmdactions 也可以省略,省略时默认的动作为打印当前输入记录(print $0) 。一条awk_cmd中的patternactions不能同时省略。

6) BEGIN区块和END区块别位于awk 脚本的开头和结尾。awk 脚本中允许只有END区块或者只有BEGIN区块。如果 awk 脚本中只有BEGIN { actions } awk不会读取input_file

7) awk把输入文件的数据读入内存,然后操作内存中的输入数据副本,awk不会修改输入文件的内容。

8) awk的总是输出到标准输出,如果想让awk输出到文件,可以使用重定向。

 

模式 pattern的分类:

序号

名称

含义

1

/正则表达式/

使用正则表达式匹配记录

2

关系表达式

使用关系运算符进行操作

3

模式匹配表达式

使用运算符~(匹配)!~(不匹配)

4

BEGIN

指定在第一条输入记录被处理之前所发生的动作

5

Pattern1pattern2

指定行的范围,该语法不包括BEGINEND模式

6

END

指定在最后一条输入记录被处理之后发生的动作

 

操作action由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内。主要有四部份:变量或数组赋值,控制语句,输入输出指令,内置函数。

 

1)变量与数组赋值

变量

·         awk中,变量不需要定义就可以直接使用,变量类型可以是数字或字符串。

·         赋值格式:Variable = expression,如$ awk '$1 ~/test/{count = $2 + $3; print count}' test,上式的作用是,awk先扫描第一个域,一旦与test匹配,就把第二个域的值加上第三个域的值,并把结果赋值给变量count,最后打印出来。

·         awk可以在命令行中给变量赋值,然后将这个变量传输给awk脚本。如$ awk -F: -f awkscript month=4 year=2004 test,上式的monthyear都是自定义变量,分别被赋值为42004。在awk脚本中,这些变量使用起来就象是在脚本中建立的一样。注意,如果参数前面出现test,那么在BEGIN语句中的变量就不能被使用。

·         域变量也可被赋值和修改,如$ awk '{$2 = 100 + $1; print }' test,上式表示,如果第二个域不存在,awk将计算表达式100$1的值,并将其赋值给$2,如果第二个域存在,则用表达式的值覆盖$2原来的值。再例如:$ awk '$1 == "root"{$1 ="test";print}' test,如果第一个域的值是“root”,则把它赋值为“test”,注意,字符串一定要用双引号。

·         内建变量的使用。变量列表在前面已列出,现在举个例子说明一下。$ awk -F: 'IGNORECASE=1; $1 == "MARY"{print NR,$1,$2,$NF}'test,把IGNORECASE设为1代表忽略大小写,打印第一个域是mary的记录数、第一个域、第二个域和最后一个域

数组

  • 用变量作为数组下标。如:$ awk '{name[x++]=$2};END{for(i=0;i。数组name中的下标是一个自定义变量xawk初始化x的值为0,在每次使用后增加1。第二个域的值被赋给name数组的各个元素。在END模块中,for循环被用于循环整个数组,从下标为0的元素开始,打印那些存储在数组中的值。因为下标是关健字,所以它不一定从0开始,可以从任何值开始。
  • special for循环用于读取关联数组中的元素。格式如下:

{for (index in array){

         print array [index]

         }

}

$ awk '/^tom/{name[NR]=$1}; END{for(i in name){print name[i]}}' test。打印有值的数组元素。打印的顺序是随机的。

  • 用字符串作为数组的下标。如:count["test"]
  • 用域值作为数组的下标。如:$ awk '{count[$1]++} END{for(name in count) print name,count[name]}' test。该语句将打印$1中字符串出现的次数。它首先以第一个域作数组count的下标,第一个域变化,索引就变化。
  • delete函数用于删除数组元素。如:$ awk '{line[x++]=$1} END{for(x in line) delete(line[x])}' test。分配给数组line的是第一个域的值,所有记录处理完成后,special for循环将删除每一个元素。

 

2)控制语句

语句

含义

if (condition) statement [ else statement ]

条件语句

while (condition) statement

循环语句

do statement while (condition)

循环语句

for (expr1; expr2; expr3) statement

循环语句

for (var in array) statement

循环语句

break

退出整个循环

continue

略过当前循环后续语句

delete array[index]

删除数组元素

delete array

删除数组

exit [ expression ]

退出语句

 

3)输入输出及重定向指令

输入指令:getline

getline从整体上来说,应这么理解它的用法: 
当其左右无重定向符 | < 时,getline作用于当前文件,读入当前文件的第一行给其后跟的变量var $0(无变量);应该注意到,由于awk在处理getline之前已经读入了一行,所以getline得到的返回结果是隔行的。

当其左右有重定向符 | < 时,getline则作用于重定向输入文件,由于该文件是刚打开,并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行。

用法及含义:

用法

含义

getline

读入下一行记录,更新$0,NF,NR,FNR

getline var

读入下一行记录到变量 var(var省略时,表示置于$0) ,更新NR,FNR

getline < file

读入文件file的一行到$0

getline var < file

读入文件file的一行到变量 var(var省略时,表示置于$0)

“command” | getline

shell命令command的输出作为getline的输入

“command” | getline var

shell命令command的输出作为getline var的输入

输入重定向需用到getline函数。getline从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。 Pattern BEGIN END , getline 将由 stdin 读取数据, 否则由awk正处理的数据文件上读取数据getline 一次读取一行资料并给NFNRFNR等内建变量赋值。如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误,例如打开文件失败,就返回-1。如:

$ awk 'BEGIN{ "date" | getline d; print d}' test。执行linuxdate命令,并通过管道输出给getline,然后再把输出赋值给自定义变量d,并打印它。

$ awk 'BEGIN{"date" | getline d; split(d,mon); print mon[2]}' test。执行shelldate命令,并通过管道输出给getline,然后getline从管道中读取并将输入赋值给dsplit函数把变量d转化成数组mon,然后打印数组mon的第二个元素。

$ awk 'BEGIN{while( "ls" | getline) print}',命令ls的输出传递给getline作为输入,循环使getlinels的输出中读取一行,并把它打印到屏幕。这里没有输入文件,因为BEGIN块在打开输入文件前执行,所以可以忽略输入文件。

$ awk 'BEGIN{printf "What is your name?"; getline name < "/dev/tty" } $1 ~name {print "Found" name on line ", NR "."} END{print "See you," name "."} test。在屏幕上打印”What is your name?",并等待用户应答。当一行输入完毕后,getline函数从终端接收该行输入,并把它储存在自定义变量name中。如果第一个域匹配变量name的值,print函数就被执行,END块打印See youname的值。

$ awk 'BEGIN{while (getline < "/etc/passwd" > 0) lc++; print lc}'awk将逐行读取文件/etc/passwd的内容,在到达文件末尾前,计数器lc一直增加,当到末尾时,打印lc的值。注意,如果文件不存在,getline返回-1,如果到达文件的末尾就返回0,如果读到一行,就返回1,所以命令 while (getline < "/etc/passwd")在文件不存在的情况下将陷入无限循环,因为返回-1表示逻辑真。

可以在awk中打开一个管道,且同一时刻只能有一个管道存在。通过close()可关闭管道。如:$ awk '{print $1, $2 | "sort" }' test END {close("sort")}awdprint语句的输出通过管道作为linux命令sort的输入,END块执行关闭管道操作。

 

输出指令:printprintf

print

范例

id = "BE-267";  ave = 89

print "ID# :", id, "Ave Score :"ave

(a)结果输出:

ID# : BE-267 Ave Score :89

(b)print 之后可接上字串常数(Constant String)或变量. 它们彼此间可用"," 隔开

(c)上式中, 字串 "ID# :" 与变量 id 之间使用","隔开, 打印时两者之间会以自动OFS隔开 OFS 之值一般内定为 "一个空格"

(d)上式中, 字串 "Ave Score :" 与变量ave之间并未以","隔开, awk会将这两者先当成字串concate在一起(变成"Ave Score :89"),再予打印。

 

printf

该指令与 C 语言中的用法相同, 可借由该指令控制输出时的格式

语法

printf ("输出模板字符串",参数列表)

范例

id = "BE-2647";  ave = 89

printf("ID# : %s   Ave Score : %d\n", id, ave)

(a)结果输出:

ID# : BE-2647   Ave Score : 89

(b)format 部分是由一般的字串(String Constant)及格式控制字符(Formatcontrol letter, 其前会加上一个%字符)所构成

格式控制符: %[-][width][.prec]fmt

% : 标识一个格式控制符的开始,不可省略。

- : 表示参数输出时左对齐,可省略。

width : 一个数字,表示参数输出时占用域的宽度,可省略。

.prec : prec是一个数值,表示最大字符串长度或小数点右边的位数,可省略。

fmt : 一个小写字母,表示输出参数的数据类型,不可省略。

常见的fmt :

格式符

说明

%d

十进制有符号整数

%u

十进制无符号整数

%f

浮点数

%s

字符串

%c

单个字符

%p

指针的值

%e

指数形式的浮点数

%x

%X 无符号以十六进制表示的整数

%o

无符号以八进制表示的整数

%g

自动选择合适的表示法

 

输出模板字符串的字符串中必须包含格式控制符,有几个参数就要求有几个格式控制符。模板字符串中可以只有格式控制符而没有其它字符。 以上式为例,"ID# : ""  Ave Score : " 为一般字串%s %d 为格式控制字符

(c)打印时, 一般字串将被原封不动地打印出来遇到格式控制字符时,则依序把 format后方之 item 转换成所指定的格式后进行打印

(d)有关的细节, 读者可从介绍 C 语言的书籍上得到较完整的介绍

(e)print printf 两个指令, 其后可使用>>>将输出到stdout 的数据重定向到其它文件

 

4)内置函数

字符串函数:

函数名称

含义

length(str)

返回字符串str的长度

index(str,substr)

返回字符串substr在字符串str中第一次出现的位置,从1开始

match(str,regex)

返回模式字符串regex在字符串str第一次出现的位置,如果不包含,则返回值0

sprintf(fmt,exp-list)

返回经fmt格式化后的exp

substr(str, n, len)

返回str的子字符串,其长度为len字符,从str的第n个位置开始。如果len没有出现,则传回的子字符串是从第n个位置开始至结束

sub(regex,sstr,tstr)

tstr中匹配正则表达式regex的第一个字符串用sstr替换

gsub(regex,sstr,tstr)

tstr中匹配正则表达式regex的每一个字符串用sstr替换

strtonum(str)

转换str为数值形式

tolower(str)

将字符串str的大写字母改为小写字母

toupper(str)

字符串string 的小写字母改为大写字母

数组函数

函数名称

含义

split( str, arr, fs )

fs为分隔符将字符串str分隔成一个awk数组arr,并返回arr的下标数

assort(a,b)

对数组a的值进行排序,把排序后的下标存入新生成的数组b中,丢弃数组a下标值

asorti(a,b)

对数组a的下标进行排序,并把排序后的下标存入新生成的数组b

数学函数

函数名称

含义

atan2( y, x )

返回 y/x 的反正切。

cos( x )

返回 x 的余弦;x 是弧度。

sin( x )

返回 x 的正弦;x 是弧度。

exp( x )

返回 x 幂函数。

log( x )

返回 x 的自然对数。

sqrt( x )

返回 x 平方根。

int( x )

返回 x 的截断至整数的值。

rand( )

返回任意数字 n,其中 0 <= n < 1

srand( [Expr] )

rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。

时间函数

函数名称

含义

systime

返回从197011日开始到当前时间(不计闰年)的整秒数

strftime

格式化时间输出,将时间戳转为时间字符串具体格式,见下表

mktime

生成时间格式

strftime日期和时间格式说明符

格式

描述

%a

星期几的缩写(Sun)

%A

星期几的完整写法(Sunday)

%b

月名的缩写(Oct)

%B

月名的完整写法(October)

%c

本地日期和时间

%d

十进制日期

%D

日期 08/20/99

%e

日期,如果只有一位会补上一个空格

%H

用十进制表示24小时格式的小时

%I

用十进制表示12小时格式的小时

%j

11日起一年中的第几天

%m

十进制表示的月份

%M

十进制表示的分钟

%p

12小时表示法(AM/PM)

%S

十进制表示的秒

%U

十进制表示的一年中的第几个星期(星期天作为一个星期的开始)

%w

十进制表示的星期几(星期天是0)

%W

十进制表示的一年中的第几个星期(星期一作为一个星期的开始)

%x

重新设置本地日期(08/20/99)

%X

重新设置本地时间(120000)

%y

两位数字表示的年(99)

%Y

当前月份

%Z

时区(PDT)

%%

百分号(%)

其他函数

函数名称

含义

close( Expression )

用同一个带字符串值的 Expression 参数来关闭由 print printf 语句打开的或调用 getline 函数打开的文件或管道。如果文件或管道成功关闭,则返回 0;其它情况下返回非零值。如果打算写一个文件,并稍后在同一个程序中读取文件,则 close 语句是必需的。

system(Command )

执行 Command 参数指定的命令,并返回退出状态。等同于 system 子例程。

 

九、awk中调用shell命令

三种方式:

方式一:system(command )

方式二:print 。。。| command

方式三:command | getline

 

十、示例

建立待处理的文件:

[root@stone ~]# df -h > dflog

[root@stone ~]# cat dflog

Filesystem            Size  Used Avail Use% Mounted on

/dev/sda2              29G  6.9G   21G  26% /

/dev/sda3             4.8G  142M  4.4G   4% /home

/dev/sda1              99M   28M   66M  30% /boot

tmpfs                 203M     0  203M   0% /dev/shm

none                  203M  104K  203M   1% /var/lib/xenstored

/dev/sda6             950M   24M  878M   3% /mnt/sda6

/dev/sda7             950M   73M  829M   9% /srv/myproject

/dev/scd0             2.2G  2.2G     0 100% /media/RHEL_4-U7 i386 Disc 1

 

1)选择特定行、列及字段:

输出指定的行

[root@stone ~]# awk 'NR==2' dflog

/dev/sda2              29G  6.9G   21G  26% /

[root@stone ~]# awk '/home/,/boot/' dflog

/dev/sda3             4.8G  142M  4.4G   4% /home

/dev/sda1              99M   28M   66M  30% /boot

[root@stone ~]# df | awk '$2>10000000'

Filesystem           1K-blocks      Used Available Use% Mounted on

/dev/sda2             29753588   7207140  21010636  26% /

 

输出指定的列

[root@stone ~]# awk '{print $5}' dflog

Use%

26%

4%

30%

0%

1%

3%

9%

100%

 

输出指定的字段

[root@stone ~]# awk 'NR==2{print $5}' dflog

26%

[root@stone ~]# awk 'NR==2,NR==3{print $1}' dflog   

/dev/sda2

/dev/sda3

 

输出正则表达式、关系表达式及模式匹配表达式匹配的行

[root@stone ~]# awk '/\/dev\/sda2/' dflog

/dev/sda2              29G  6.9G   21G  26% /

[root@stone ~]# awk '/^(\/dev\/sda|Filesystem)/' dflog

Filesystem            Size  Used Avail Use% Mounted on

/dev/sda2              29G  6.9G   21G  26% /

/dev/sda3             4.8G  142M  4.4G   4% /home

/dev/sda1              99M   28M   66M  30% /boot

/dev/sda6             950M   24M  878M   3% /mnt/sda6

/dev/sda7             950M   73M  829M   9% /srv/myproject

[root@stone ~]# sed 's/%//g' dflog | awk '/^\/dev\/sda/{if ($5>25) print $1}'

/dev/sda2

/dev/sda1

[root@stone ~]# sed 's/%//g' dflog | awk '/^\/dev\/sda/ && $5>25'

/dev/sda2              29G  6.9G   21G  26 /

/dev/sda1              99M   28M   66M  30 /boot

[root@stone ~]# sed 's/%//g' dflog | awk '/^\/dev\/sda/{print($5>25? $1" error":$1" ok")}'

/dev/sda2 error

/dev/sda3 ok

/dev/sda1 error

/dev/sda6 ok

/dev/sda7 ok

[root@stone ~]# awk '$6~/\/home/{print $1}' dflog

/dev/sda3

[root@stone ~]# awk '$6!~/\/home/{print $1}' dflog

Filesystem

/dev/sda2

/dev/sda1

tmpfs

none

/dev/sda6

/dev/sda7

/dev/scd0

 

2BEGIN的用法

BEGIN常用于打印信息,初始化变量,包括内置变量, 在第一条输入记录被处理之前所发生的动作

[root@stone ~]# awk 'BEGIN{FS=":"}$3<5{print $1,$3}' /etc/passwd 

root 0

bin 1

daemon 2

adm 3

lp 4

[root@stone ~]# awk 'BEGIN{OFS=":"}NR==1,NR==3{print $1,$5,$6}' dflog

Filesystem:Use%:Mounted

/dev/sda2:26%:/

/dev/sda3:4%:/home

 

3END的用法

END常用于打印信息,在最后一条输入记录被处理之后所发生的动作

[root@stone ~]# df | sed -n '2,$p'| awk '{count+=$2}END{print "the total is "count}'

the total is 39459888

[root@stone ~]# df | awk 'NR>=2{count+=$2}END{print "the total is "count}'              

the total is 39459888

 

4)内置函数

[root@stone ~]# awk '/^\/dev\/sda/{gsub(/%/,"");if ($5>25) print $1}' dflog

/dev/sda2

/dev/sda1

[root@stone ~]# awk '/^\/dev\/sda/{gsub(/%/,"",$5);if ($5>25) print $1}' dflog

/dev/sda2

/dev/sda1

请使用浏览器的分享功能分享到微信等