返回首页 shell 脚本编程

shell 学习十七天---awk 命令

使用 awk 重新编排字段

awk 非常擅长处理结构化数据和生成表单.和 sed 和 grep 很相似.由于 awk 具备各种及哦啊本语言的特点,所以可以把它看做是一种脚本语言.
先来看个案例,只查看/etc/passwd/目录下的用户名和组名

awk -F: ‘{print $1,$5}’ /etc/passwd
意思是:使用:来分割这一行,把这一行的第一和第五个字段打印出来.
调用 awk:

  • 第一种方式:
    awk [-F 分隔符] ‘commands’ input-file(s)
    这里的 commands 是真正的 awk 命令,[-F 分隔符]适可选的,awk 默认使用空格分隔,因此如果要浏览域间有空格的文本,不必指定这个选项,但如果浏览如 passwd 文件,此文件各域使用冒号作为分隔符,则必须使用-F 选项: awk -F : 'commands' input-file

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

  • 第三种方式
    将所有 awk 命令插入一个单独文件,然后调用,如: awk -f awk-script-file input-file
    -f 选项指明在文件 awk-script-file 的 awk 脚本,input-file 是使用 awk 进行浏览的文件名

任何 awk 语句都是由模式和动作组成,在一个 awk 脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。动作即对数据进行的操作,如果省去模式部分,动作将时刻保持执行状态

模式可以是任何条件语句或复合语句或正则表达式,模式包含两个特殊字段 BEGIN 和 END,使用 BEGIN 语句设置计数和打印头,BEGIN 语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行;END 语句用来在 awk 完成文本浏览动作后打印输出文本总数和结尾状态标志,有动作必须使用{}括起来

实际动作在大括号{}内指明,常用来做打印动作,但是还有更长的代码如 if 和循环 looping 语句及循环退出等,如果不指明采取什么动作,awk 默认打印出所有浏览出的记录

awk 执行时,其浏览标记为$1,$2...$n,这种方法称为域标记。使用$1,$3 表示参照第 1 和第 3 域,注意这里使用逗号分隔域,使用$0 表示使用所有域。例
awk -F :‘{print $0}’ /etc/passwd //表示打印所有域并把结果重定向到/etc/passwd 中(所谓的域就是某一行中的字段)

awk -F : ‘{print $0}’ /etc/passwd ///在屏幕上显示出来

awk ‘{print $1,$4}’ /etc/passwd //只打印第一和第四域(第一和第四字段)

awk -F: ‘BRGIN{print ”hahaha\n---”}{print $1 “\t” $4}’ /etc/passwd //表示打印头信息,在输入的内容的第一行前加上”hahaha”,同时内容之间用 tab 键分开.

awk -F: 'BEGIN{print "hahaha\n---"}{print $1 "\t" $4}END{print "end\n"}' /etc/passwd //这个代表的意思是说打印开头结尾

awk 的条件匹配符 <、<=、==、!=、>=、~匹配正则表达式、!~不匹配正则表达式

匹配:awk -F: '{if($1~/root/)print $0}' /etc/passwd //在/etc/passwd 这个文件中,如果某条记录的第一个字段含有 root 就打印整条记录到屏幕上,注意,只要包含就行.

精确匹配 : awk -F: '$1=="root"{print $0}' /etc/passwd //某行中的第一个字段必须等于 root 才打印.

不匹配 : awk -F: '$0!~"root"{print $0}' /etc/passwd打印整条不包含 root 的记录,使用双引号或者反斜杠都是一样的.

其他的操作符具体不在介绍.
awk 的设计目的就是操作记录与字段:awk 读取输入记录(通常是一些行),然后自动将各个记录且分为字段.awk 将每条记录内的字段树木,存储到内建变量 NF.

通过上面的例子,差不多已经总体上有了一定得了解:
awk ‘{print $NF}’ 打印最后一行
比较特殊的字段是编号 0,表示整条记录.

awk 内置变量
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk 浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F 选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符

案例:
统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:

awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd

除了 awk 的内置变量,awk 还可以自定义变量.
例如:统计/etc/passwd 的行数:

awk '{count++}END{print count}' /etc/passwd

count 是自定义变量,这里没有初始化 count,虽然默认是 0,但是妥当的做法还是初始化为 0.

awk 'BEGIN{count=0}{count=count+1}END{print count}' /etc/passwd

例如:统计某个文件夹下的文件占用的字节数

ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}'

如果按照 M 为单位显示

ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}'

小结:
如果需要从输入的数据文件夹中取出特定的文本行,主要的工具为 grep 程序.

sed 是处理简单字符串替换的主要工具.大部分 shell 脚本在使用 sed 时几乎都是用来做替换的操作.
“从最左边开始,扩展至最长”这个法则描述了匹配的文本在何处匹配以及匹配扩展到多长.在使用 sed,awk 或其他交互式文本编辑程序时,这个法则相当重要.

cut 命令用以剪下选定的字符范围或字段,join 则是用来结合记录中具有共同键值的字段的文件.

awk 多半用于简单的”单命令行程序”,当你想要只显示选定的字段,或是重新安排行内的字段顺序时,就是 awk 排上用场的时候了.由于 awk 还是编程语言,即使在尖端的程序里,他也能发挥强大的作用.

上一篇: join 练习 下一篇: 文本排序