awk指令学习

从文本中抽取特定的信息,并显示出来
一次读取一行文本,并按字符的分隔符切割

gawk
nawk
awk [options]  'script' file1  file2,.....
awk [options] 'pattern {action}' file1,file2,...
print:只打印格式,不可自定义
printf:可自定义打印格式
 

a w k语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息。a w k抽取信息后,

才能进行其他文本操作。完整的a w k脚本通常用来格式化文本文件中的信息。

1 调用awk
有三种方式调用a w k,第一种是命令行方式,如:
awk [-F fild-separator] 'commands' input-file(s)
这里,c o m m a n d s是真正的a w k命令。
上面例子中, [ - F域分隔符]是可选的,因为a w k使用空格作为缺省的域分隔符,因此如果要浏览

域间有空格的文本,不必指定这个选项,但如果要浏览诸如p a s s w d文件,此文件各域以冒号作

为分隔符,则必须指明- F选项,如:
awk -F:  'commands' input-file(s)

第二种方法是将所有a w k命令插入一个文件,并使a w k程序可执行,然后用a w k命令解释器作为

脚本的首行,以便通过键入脚本名称来调用它。

第三种方式是将所有的a w k命令插入一个单独文件,然后调用:
awk -f awk-script-file input-files(s)
- f选项指明在文件a w k _ s c r i p t _ f i l e中的a w k脚本, i n p u t _ f i l e ( s )是使用a w k进行

浏览的文件名。

2 awk脚本
在命令中调用a w k时,a w k脚本由各种操作和模式组成。
如果设置了- F选项,则a w k每次读一条记录或一行,并使用指定的分隔符分隔指定域,但如果未

设置- F选项,a w k假定空格为域分隔符,并保持这个设置直到发现一新行。当新行出现时,a w k

命令获悉已读完整条记录,然后在下一个记录启动读命令,这个读进程将持续到文件尾或文件不再

存在。

参照表,a w k每次在文件中读一行,找到域分隔符(这里是符号#),设置其为域n,直至一新行

(这里是缺省记录分隔符),然后,划分这一行作为一条记录,接着a w k再次启动下一行读进程。

awk读文件记录的方式
域1                         分隔符        域2                分隔符        域3        分隔符        域4及换行
P. B u n n y (记录1 )         #         0 2 / 9 9         #         4 8         #         Yellow \n
J . Tr o l l (记录2 )         #         0 7 / 9 9         #         4 8 4 2 #         Brown-3 \n

2.1 模式和动作
任何a w k语句都由模式和动作组成。在一个a w k脚本中可能有许多语句。模式部分决定动作语句

何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。
模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段B E G I N和E N D。使

用B E G I N语句设置计数和打印头。B E G I N语句使用在任何文本浏览动作之前,之后文本浏览动

作依据输入文件开始执行。E N D语句用来在a w k完成文本浏览动作后打印输出文本总数和结尾状

态标志。如果不特别指明模式, a w k总是匹配或打印行数。
实际动作在大括号{ }内指明。动作大多数用来打印,但是还有些更长的代码诸如i f和循环(l o o p i

n g)语句及循环退出结构。如果不指明采取动作, a w k将打印出所有浏览出来的记录。

2. 域和记录
a w k执行时,其浏览域标记为$ 1,$ 2 . . . $ n。这种方法称为域标识。使用这些域标识将更容易

对域进行进一步处理。
使用$ 1 , $ 3表示参照第1和第3域,注意这里用逗号做域分隔。如果希望打印一个有5个域的记录的

所有域,不必指明$ 1 , $ 2 , $ 3 , $ 4 , $ 5,可使用$ 0,意即所有域。Aw k浏览时,到达一新行,

即假定到达包含域的记录末尾,然后执行新记录下一行的读动作,并重新设置域分隔。
注意执行时不要混淆符号$和s h e l l提示符$,它们是不同的。
为打印一个域或所有域,使用p r i n t命令。这是一个a w k动作(动作语法用圆括号括起来)。

1. 抽取域
真正执行前看几个例子,现有一文本文件g r a d e . t x t,记录了一个称为柔道数据库的行信息。
$ cat grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99   4712 Brown-2 12 30 28
此文本文件有7个域,即(1)名字、(2)升段日期、(3)学生序号、(4)腰带级别、(5)年龄

、(6)目前比赛积分、(7)比赛最高分。
因为域间使用空格作为域分隔符,故不必用- F选项划分域,现浏览文件并导出一些数据。在例子中

为了利于显示,将空格加宽使各域看得更清晰。

2. 保存a w k输出
有两种方式保存s h e l l提示符下a w k脚本的输出。最简单的方式是使用输出重定向符号>文件名,

下面的例子重定向输出到文件w o w。
$ awk '{print $0}' grade.txt >wow
$ cat grade.txt
使用这种方法要注意,显示屏上不会显示输出结果。因为它直接输出到文件。只有在保证输出结果

正确时才会使用这种方法。它也会重写硬盘上同名数据。

第二种方法是使用t e e命令,在输出到文件的同时输出到屏幕。在测试输出结果正确与否时多使用

这种方法。例如输出重定向到文件d e l e t e _ m e _ a n d _ d i e,同时输出到屏幕。使用这种方

法,在a w k命令结尾写入| tee delete_me_and_die。
$ awk '{print $0}' grade.txt | tee delete_me_and_die

3. 使用标准输入
在深入讲解这一章之前,先对a w k脚本的输入方法简要介绍一下。实际上任何脚本都是从标准输入

中接受输入的。为运行本章脚本,使用a w k脚本输入文件格式,例如:
belts.awk grade_student.txt
也可替代使用下述格式:
使用重定向方法:
belts.awk < grade2.txt
或管道方法:
grade2.txt | belts.awk

4. 打印所有记录
$ awk '{print $0}' grade.txt
a w k读每一条记录。因为没有模式部分,只有动作部分{print $0}(打印所有记录),这个动作必须

用花括号括起来。上述命令打印整个文件。

5. 打印单独记录
假定只打印学生名字和腰带级别,通过查看域所在列,可知为f i e l d - 1和f i e l d - 4,因此可以

使用$ 1和$ 4,但不要忘了加逗号以分隔域。
$ awk '{print $1,$4}' grade.txt
M.Tans Green
J.Lulu green
P.Bunny Yellow
J.Troll Brown-3
L.Tansl Brown-2

6. 打印报告头
上述命令输出在名字和腰带级别之间用一些空格使之更容易划分,也可以在域间使用t a b键加以划

分。为加入t a b键,使用t a b键速记引用符\ t,后面将对速记引用加以详细讨论。也可以为输出文

本加入信息头。本例中加入n a m e和b e l t及下划线。下划线使用\ n,强迫启动新行,并在\ n下

一行启动打印文本操作。打印信息头放置在B E G I N模式部分,因为打印信息头被界定为一个动作

,必须用大括号括起来。在a w k查看第一条记录前,信息头被打印。
$ awk 'BEGIN {print "Name Belt\n-----------------------------------"}{print $1"\t",$4}'

grade.txt
Name Belt
-----------------------------------
M.Tans   Green
J.Lulu   green
P.Bunny  Yellow
J.Troll  Brown-3
L.Tansl  Brown-2

7. 打印信息尾
如果在末行加入end of report信息,可使用E N D语句。E N D语句在所有文本处理动作执行完之

后才被执行。E N D语句在脚本中的位置放置在主要动作之后。下面简单打印头信息并告之查询动

作完成。
$ awk 'BEGIN {print "Name\n--------"}{print $1} END {print "end-of-report"}' grade.txt
Name
--------
M.Tans
J.Lulu
P.Bunny
J.Troll
L.Tansl
end-of-report

8. awk错误信息提示
几乎可以肯定,在使用a w k时,将会在命令中碰到一些错误。a w k将试图打印错误行,但由于大

部分命令都只在一行,因此帮助不大。
系统给出的显示错误信息提示可读性不好。使用上述例子,如果丢了一个双引号, a w k将返回:
$ awk 'BEGIN {print "Name\n--------}{print $1} END {"end-of-report"}' grade.txt
awk: cmd. line:1: BEGIN {print "Name\n--------}{print $1} END {"end-of-report"}
awk: cmd. line:1:       

当第一次使用a w k时,可能被错误信息搅得不知所措,但通过长时间和不断的学习,可总结出以下

规则。在碰到a w k错误时,可相应查找:
" 确保整个a w k命令用单引号括起来。
" 确保命令内所有引号成对出现。
" 确保用花括号括起动作语句,用圆括号括起条件语句。
" 可能忘记使用花括号,也许你认为没有必要,但a w k不这样认为,将按之解释语法

9.awk 键盘输入
如果在命令行并没有输入文件g r a d e . t x t,将会怎样?
$ awk 'BEGIN {print "Name\n--------"}{print $1} END {"end-of-report"}'
Name
--------
B E G I N部分打印了文件头,但a w k最终停止操作并等待,并没有返回s h e l l提示符。这是因为a

w k期望获得键盘输入。因为没有给出输入文件, a w k假定下面将会给出。如果愿意,顺序输入相

关文本,并在输入完成后敲<Ct r l - D >键。如果敲入了正确的域分隔符, a w k会像第一个例子一

样正常处理文本。这种处理并不常用,因为它大多应用于大量的打印稿。


2.3 awk中正则表达式及其操作

2.4元字符
这里是a w k中正则表达式匹配操作中经常用到的字符,详细情况请参阅本书第7章正则表达式概述


\ ^ $ . [] | () * + ?
这里有两个字符第7章没有讲到,因为它们只适用于a w k而不适用于g r e p或s e d。它们是:
+ 使用+匹配一个或多个字符。
? 匹配模式出现频率。例如使用/X Y?Z/匹配X Y Z或Y Z。

条件操作符
a w k条件操作符
操作符描述操作符描述
< 小于> = 大于等于
< = 小于等于~ 匹配正则表达式
= = 等于!~ 不匹配正则表达式
!= 不等于

1. 匹配
为使一域号匹配正则表达式,使用符号‘~’后紧跟正则表达式,也可以用i f语句。a w k中i f后面

的条件用()括起来。
观察文件g r a d e . t x t,如果只要显示b r o w n腰带级别可知其所在域为f i e l d - 4,这样可以写

出表达式{if($4~/brown/) print }意即如果f i e l d - 4包含b r o w n,打印它。如果条件满足,则

打印匹配记录行。可以编写下面脚本,因为这是一个动作,必须用花括号{ }括起来。
[root@Linux_chenwy sam]# awk '{if($4~/Brown/) print $0}' grade.txt
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28

2. 精确匹配
假定要使字符串精确匹配,比如说查看学生序号4 8,文件中有许多学生序号包含4 8,如果在f i e l

d - 3中查询序号4 8,a w k将返回所有序号带4 8的记录:
[root@Linux_chenwy sam]# awk '{if($3~/48/) print$0}' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26

为精确匹配4 8,使用等号= =,并用单引号括起条件。例如$ 3
[root@Linux_chenwy sam]# awk '$3=="48" {print$0}' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28
[root@Linux_chenwy sam]# awk '{if($3=="48") print$0}' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28

3. 不匹配
有时要浏览信息并抽取不匹配操作的记录,与~相反的符号是!~,意即不匹配。像原来使用查询b r

o w n腰带级别的匹配操作一样,现在看看不匹配情况。表达式$0 !~/brown/,意即查询不包含模

式b r o w n腰带级别的记录并打印它。
注意,缺省情况下, a w k将打印所有匹配记录,因此这里不必加入动作部分。
[root@Linux_chenwy sam]# awk '$0 !~ /Brown/' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28

4. 小于
看看哪些学生可以获得升段机会。测试这一点即判断目前级别分f i e l d - 6是否小于最高分f i e l d

- 7,在输出结果中,加入这一改动很容易。
[root@Linux_chenwy sam]# awk '{if($6 < $7) print $0}' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26

5. 小于等于
对比小于,小于等于只在操作符上做些小改动,满足此条件的记录也包括上面例子中的输出情况。
[root@Linux_chenwy sam]# awk '{if($6 <= $7) print $1}' grade.txt
M.Tans
J.Lulu
J.Troll

6. 大于
[root@Linux_chenwy sam]# awk '{if($6 > $7) print $1}' grade.txt
P.Bunny
L.Tansl

7. 设置大小写
为查询大小写信息,可使用[ ]符号。在测试正则表达式时提到可匹配[ ]内任意字符或单词,因此若

查询文件中级别为g r e e n的所有记录,不论其大小写,表达式应为‘ / [ G g ] r e e n /’
[root@Linux_chenwy sam]# awk '/[Gg]reen/' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26

8. 任意字符
抽取名字,其记录第一域的第四个字符是a,使用句点.。表达式/ ^ . . . a /意为行首前三个字符任意

,第四个是a,尖角符号代表行首。
[root@Linux_chenwy sam]# awk '$1 ~ /^...a/' grade.txt
M.Tans 5/99 48311 Green 8 40 44
L.Tansl 05/99 4712 Brown-2 12 30 28

9. 或关系匹配
为抽取级别为y e l l o w或b r o w n的记录,使用竖线符|。意为匹配| 两边模式之一。注意,使用竖

线符时,语句必须用圆括号括起来。
[root@Linux_chenwy sam]# awk '$0 ~/(Yellow|Brown)/' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28
上面例子输出所有级别为Ye l l o w或B r o w n的记录。

使用这种方法在查询级别为G r e e n或g r e e n时,可以得到与使用[ ]表达式相同的结果。
[root@Linux_chenwy sam]# awk '/^M/' grade.txt
M.Tans 5/99 48311 Green 8 40 44

10. 行首
不必总是使用域号。如果查询文本文件行首包含M的代码,可简单使用下面^符号:
[root@Linux_chenwy sam]# awk '/^M/' grade.txt

复合表达式即为模式间通过使用下述各表达式互相结合起来的表达式:
&& AND : 语句两边必须同时匹配为真。
|| O R:语句两边同时或其中一边匹配为真。
! 非求逆

11. AND
打印记录,使其名字为‘ P. B u n n y且级别为Ye l l o w,使用表达式( $ 1 = = " P. B u n n y " &

&$ 4 = = " Ye l l o w " ),意为& &两边匹配均为真。完整命令如下:
[root@Linux_chenwy sam]# awk '{if ($1=="P.Bunny" && $4=="Yellow") print $0}' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28

12. Or
如果查询级别为Ye l l o w或B r o w n,使用或命令。意为“ | |”符号两边的匹配模式之一或全部

为真。
[root@Linux_chenwy sam]# awk '{if ($4=="Yellow" || $4~/Brown/) print $0}' grade.txt
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28

awk内置变量
a w k有许多内置变量用来设置环境信息。这些变量可以被改变。表9 - 3显示了最常使用的一些变

量,并给出其基本含义。
awk内置变量
A R G C 命令行参数个数
A R G V 命令行参数排列
E N V I R O N 支持队列中系统环境变量的使用
FILENAME a w k浏览的文件名
F N R 浏览文件的记录数
F S 设置输入域分隔符,等价于命令行- F选项
N F 浏览记录的域个数
N R 已读的记录数
O F S 输出域分隔符
O R S 输出记录分隔符
R S 控制记录分隔符

NF、NR和FILENAME
要快速查看记录个数,应使用N R。比如说导出一个数据库文件后,如果想快速浏览记录个数,以

便对比于其初始状态,查出导出过程中出现的错误。使用N R将打印输入文件的记录个数。print

NR放在E N D语法中。

如:所有学生记录被打印,并带有其记录号。使用N F变量显示每一条读记录中有多少个域,并在E

N D部分打印输入文件名。
[root@chenwy sam]# awk '{print NF,NR,$0} END{print FILENAME}' grade.txt
7 1 M.Tans 5/99 48311 Green 8 40 44
7 2 J.Lulu 06/99 48317 green 9 24 26
7 3 P.Bunny 02/99 48 Yellow 12 35 28
7 4 J.Troll 07/99 4842 Brown-3 12 26 26
7 5 L.Tansl 05/99       4712 Brown-2 12 30 28
grade.txt

 

awk操作符
1. 设置输入域到域变量名
在a w k中,设置有意义的域名是一种好习惯,在进行模式匹配或关系操作时更容易理解。
一般的变量名设置方式为n a m e = $ n,这里n a m e为调用的域变量名, n为实际域号。例如设

置学生域名为n a m e,级别域名为b e l t,操作为n a m e = $ 1 ; b e l t s = $ 4。注意分号的使用

,它分隔a w k命令。下面例子中,重新赋值学生名域为n a m e,级别域为b e l t s。查询级别为

Ye l l o w的记录,并最终打印名称和级别。
$ awk '{name=$1;belts=$4;if(belts ~/Yellow/) print name" is belt "belts}' grade.txt
P.Bunny is belt Yellow

2. 域值比较操作
有两种方式测试一数值域是否小于另一数值域。
1) 在B E G I N中给变量名赋值。
2) 在关系操作中使用实际数值。
通常在B E G I N部分赋值是很有益的,可以在a w k表达式进行改动时减少很多麻烦。
使用关系操作必须用圆括号括起来。
下面的例子查询所有比赛中得分在2 7点以下的学生。
用引号将数字引用起来是可选的,“2 7”、2 7产生同样的结果。
[sam@chenwy sam]$ awk '{if ($6<$7) print $0}' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26

第二个例子中给数字赋以变量名B A S E L I N E和在B E G I N部分给变量赋值,两者意义相同。
[sam@chenwy sam]$ awk 'BEGIN{BASELINE="27"} {if ($6<BASELINE) print $0}' grade.txt
J.Lulu 06/99 48317 green 9 24 26
J.Troll 07/99 4842 Brown-3 12 26 26

7. 增加列值
为增加列数或进行运行结果统计,使用符号+ =。增加的结果赋给符号左边变量值,增加到变量的

域在符号右边。例如将$ 1加入变量t o t a l,表达式为t o t a l + = $ 1。列值增加很有用。许多文

件都要求统计总数,但输出其统计结果十分繁琐。在a w k中这很简单,请看下面的例子。
将所有学生的‘目前级别分’加在一起,方法是t o t + = $ 6,t o t即为a w k浏览的整个文件的域

6结果总和。所有记录读完后,在E N D部分加入一些提示信息及域6总和。不必在a w k中显示说明

打印所有记录,每一个操作匹配时,这是缺省动作。
[sam@chenwy sam]$ awk '(tot+=$6); END{print "Club student total points :" tot}'
grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28
Club student total points :155

如果文件很大,你只想打印结果部分而不是所有记录,在语句的外面加上圆括号()即可。
[sam@chenwy sam]$ awk '{(tot+=$6)}; END{print "Club student total points :" tot}'

grade.txt
Club student total points :155


内置的字符串函数
awk内置字符串函数
g s u b ( r, s ) 在整个$ 0中用s替代r
g s u b ( r, s , t ) 在整个t中用s替代r
i n d e x ( s , t ) 返回s中字符串t的第一位置
l e n g t h ( s ) 返回s长度
m a t c h ( s , r ) 测试s是否包含匹配r的字符串
s p l i t ( s , a , f s ) 在f s上将s分成序列a
s p r i n t ( f m t , e x p ) 返回经f m t格式化后的e x p
s u b ( r, s ) 用$ 0中最左边最长的子串代替s
s u b s t r ( s , p ) 返回字符串s中从p开始的后缀部分
s u b s t r ( s , p , n ) 返回字符串s中从p开始长度为n的后缀部分

g s u b函数有点类似于s e d查找和替换。它允许替换一个字符串或字符为另一个字符串或字符,并

以正则表达式的形式执行。第一个函数作用于记录$ 0,第二个g s u b函数允许指定目标,然而,

如果未指定目标,缺省为$ 0。
i n d e x(s,t)函数返回目标字符串s中查询字符串t的首位置。l e n g t h函数返回字符串s字符长

度。
m a t c h函数测试字符串s是否包含一个正则表达式r定义的匹配。s p l i t使用域分隔符f s将字符串s

划分为指定序列a。
s p r i n t函数类似于p r i n t f函数(以后涉及),返回基本输出格式f m t的结果字符串e x p。
s u b(r,s)函数将用s替代$ 0中最左边最长的子串,该子串被( r)匹配。
s u b(s,p)返回字符串s在位置p后的后缀。s u b s t r(s,p,n)同上,并指定子串长度为n。
现在看一看a w k中这些字符串函数的功能。

1. gsub
要在整个记录中替换一个字符串为另一个,使用正则表达式格式, /目标模式/,替换模式/。例如改

变学生序号4 8 4 2到4 8 9 9:
[root@Linux_chenwy root]# cd /usr/sam
[root@Linux_chenwy sam]# awk 'gsub(/4842/,4899){print $0}' grade.txt
J.Troll 07/99 4899 Brown-3 12 26 26

[root@Linux_chenwy sam]# awk 'gsub(/4842/,4899)' grade.txt
J.Troll 07/99 4899 Brown-3 12 26 26

3. length
返回所需字符串长度,例如检验字符串J . Tr o l l返回名字及其长度,即人名构成的字符个数
[root@Linux_chenwy sam]# awk '$1=="J.Troll" {print length($1)" "$1}' grade.txt
7 J.Troll
还有一种方法,这里字符串加双引号。
[root@Linux_chenwy sam]# awk 'BEGIN{print length("A FEW GOOD MEN")}'
14


4. match
m a t c h测试目标字符串是否包含查找字符的一部分。可以对查找部分使用正则表达式,返回值为

成功出现的字符排列数。如果未找到,返回0,第一个例子在A N C D中查找d。因其不存在,所以

返回0。第二个例子在A N C D中查找D。因其存在,所以返回A N C D中D出现的首位置字符数。

第三个例子在学生J . L u l u中查找u。
[root@Linux_chenwy sam]# awk 'BEGIN{print match("ANCD",/d/)}'
0
[root@Linux_chenwy sam]# awk 'BEGIN{print match("ANCD",/D/)}'
4
[root@Linux_chenwy sam]# awk '$1=="J.Lulu" {print match($1,"u")}' grade.txt
4


6. sub
如:学生J . Tr o l l的记录有两个值一样,“目前级别分”与“最高级别分”。只改变第一个为2 9

,第二个仍为2 4不动,操作命令为s u b(/ 2 6 /," 2 9 ",$ 0),只替换第一个出现2 4的位置。

注意J . Tr o l l记录需存在。
[root@Linux_chenwy sam]# awk '$1=="J.Troll" sub(/26/,"29",$0)' grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 29
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 29 26
L.Tansl 05/99 4712 Brown-2 12 30 28

7. substr
s u b s t r是一个很有用的函数。它按照起始位置及长度返回字符串的一部分。例子如下:
[root@Linux_chenwy sam]# awk '$1=="L.Tansl" {print substr($1,1,3)}' grade.txt
L.T
上面例子中,指定在域1的第一个字符开始,返回其前面3个字符。

如果给定长度值远大于字符串长度, a w k将从起始位置返回所有字符,要抽取L Ta n s l - e y的姓

,只需从第3个字符开始返回长度为7。可以输入长度9 9,a w k返回结果相同。
[root@Linux_chenwy sam]# awk '$1=="L.Tansl" {print substr($1,1,99)}' grade.txt
L.Tansl

s u b s t r的另一种形式是返回字符串后缀或指定位置后面字符。这里需要给出指定字符串及其返回

字串的起始位置。例如,从文本文件中抽取姓氏,需操作域1,并从第三个字符开始:
[root@Linux_chenwy sam]# awk '{print substr($1,3)}' grade.txt
Tans
Lulu
Bunny
Troll
Tansl
还有一个例子,在B E G I N部分定义字符串,在E N D部分返回从第t个字符开始抽取的子串。
[root@Linux_chenwy sam]# awk 'BEGIN{STR="A FEW GOOD MEN"}END{print substr

(STR,7)}' grade.txt
GOOD MEN


使用管道将字符串s t a n d - b y传入a w k,返回其长度。
[root@Linux_chenwy sam]# echo "Stand-by" | awk '{print length($0)}'
8

设置文件名为一变量,管道输出到a w k,返回不带扩展名的文件名。
[root@Linux_chenwy sam]# STR="mydoc.txt"
[root@Linux_chenwy sam]# echo $STR|awk '{print substr($STR,1,5)}'
mydoc

设置文件名为一变量,管道输出到a w k,只返回其扩展名。
[root@Linux_chenwy sam]# STR="mydoc.txt"
[root@Linux_chenwy sam]# echo $STR|awk '{print substr($STR,7)}'
txt

分割线
感谢打赏
江西数库信息技术有限公司
YWSOS.COM 平台代运维解决方案
 评论
 发表评论
姓   名:

Powered by AKCMS