您的位置:首页 > 运维架构 > Shell

shell文本过滤编程(二):awk之基础

2014-08-24 21:55 260 查看
【版权声明:转载请保留出处:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】

    上一节说到了grep命令,grep命令主要用在获取符合规则的行信息。本节要讲的awk在对某文件或字符串中获取指定文本域有较强大的功能。

a w k语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息。 a w k抽取信息后,才能进行其他文本操作。完整的 a w k脚本通常用来格式化文本文件中的信息。

在命令行上调用awk命令式最常用的使用awk的方式:

awk [-F separator] ‘cmd’ filename

cmd是真正的awk命令,[-F 域分隔符]是可选的,因为 a w k使用空格作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,但如果要浏览诸如 p a s s w d文件,此文件各域以冒号作为分隔符,则必须指明 - F选项,如:

awk -F: ‘{cmd}’ /etc/passwd

awk在调用时,会每次读一条记录或一行,并使用指定的分割域分割指定域(未设置分割域时默认为空格),然后标记为 $ 1,$ 2 . . . $ n,使用这些域标识将更容易对域进行进一步处理。 然后执行awk的命令部分操作,然后awk再开始读入下一行内容,直到读完整个文件。

awk命令动作在大括号 { }内指明。动作大多数用来打印,但是还有些更长的代码诸如 if和循环(looping)语句及循环退出结构。

再讲示例之前先构造一个文件(来自/etc/group文件的修改),如下:
# cat group_file1
wireshark x 987
usbmon x 986
jackuser x 985
vboxusers x 984 allen
aln x 1001
#
第一个示例:
# awk '{print}' group_file1
wireshark x 987
usbmon x 986
jackuser x 985
vboxusers x 984 allen
aln x 1001
#
该命令和cat 命令效果一样,都是直接把文件内容直接输出。该awk的命令部分为print,执行awk时,依次对每一行执行print命令,他会把文件每一行内容都打印出来。此处也可以有其他代码,也可以和输入进来的行无关。比如执行:
# awk '{print "hello awk!"}' group_file1
hello awk!
hello awk!
hello awk!
hello awk!
hello awk!
有多少行文件就会答应多少行hello awk!

awk 非常善于处理分成多个逻辑字段的文本,而且让您可以毫不费力地引用 awk 脚本中每个独立的字段。对上面文件,我们可以提取每一行的第一列和第三列内容(未指定-F时,默认为空格),如下:
# awk '{print $1 $3}' group_file1
wireshark987
usbmon986
jackuser985
vboxusers984
aln1001
输出结果黏在一起了,我们可以加入一些字符分割它:
# awk '{print "group:"$1 "\tid:"$3}' group_file1
group:wireshark id:987
group:usbmon    id:986
group:jackuser  id:985
group:vboxusers id:984
group:aln     id:1001
在{}里面,及时$1之间$3有空格,也不会打印出空格,需要我们自己加入字符串来输出分割打印,也可以加入一个逗号,这样输出时会有一个空格分割。

这样是不是好看多了,有没有一种awk很牛B的感觉,不着急,才刚刚开始。

像其他shell命令一样,awk命令也可以放在脚本文件中。通过执行脚本文件来执行awk命令。脚本内容以及执行结果如下:
# cat 1_awk.sh
#!/bin/sh
awk '{print "name:"$1 "\tid:"$3}' group_file1
# ./1_awk.sh
name:wireshark  id:987
name:usbmon    id:986
name:jackuser   id:985
name:vboxusers  id:984
name:aln      id:1001
通常,对于每个输入行,awk 都会执行每个脚本代码块一次。然而,在许多编程情况中,可能需要在 awk 开始处理输入文件中的文本之前执行初始化代码。对于这种情况,awk 允许您定义一个 BEGIN 块。 awk 在开始处理输入文件之前会执行 BEGIN 块,因此它是初始化 FS(字段分隔符)变量、打印页眉或初始化其它在程序中以后会引用的全局变量的极佳位置。

awk 还提供了另一个特殊块,叫作 END 块。awk 在处理了输入文件中的所有行之后执行这个块。通常,END 块用于执行最终计算或打印应该出现在输出流结尾的摘要信息。

修改一下上面的例子,加入BEGIN 和END 块:
#!/bin/sh
awk '
BEGIN {
print "    Name\tID\n==========================="
}
{
print "name:"$1 "\tid:"$3
}
END {
print "=============END============="
}
' group_file1
对于不是以空格分割的行,可以使用-F设置分隔符号,比如下面文件:
# cat group_file2
wireshark:x:987:
usbmon:x:986:
jackuser:x:985:
vboxusers:x:984:allen
aln:x:1001:
# awk -F: '{print $1, $3}' group_file2
wireshark 987
usbmon 986
jackuser 985
vboxusers 984
aln 1001

在后面我们有另外一种方法设置分割符号,就是设置FS变量。

awk 也可以写成以awk程序解释执行的脚本文件中,然后在命令行上以

awk  -f xxx.awk filename

调用执行。

Awk脚本文件如下:#!/bin/awk
BEGIN {
print "============begin=========="
}
{
print "++++++++++cmd++++++++++"
}
END {

print "-----------End---------"
}
调用该脚本如下:
# awk -f begin_cmd.awk group_file1
============begin==========
++++++++++cmd++++++++++
++++++++++cmd++++++++++
++++++++++cmd++++++++++
++++++++++cmd++++++++++
++++++++++cmd++++++++++
-----------End---------

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: