awk编程?let‘s go(一) ---- 初识awk

21 篇文章 1 订阅
8 篇文章 0 订阅


温馨提示,本文适合有一定编程基础的人阅读。

前言

在学习本文之前,相信有一部分人和我之前一样,对awk的认知停留于对某个简单命令的使用。对于我们做 java 开发的,最经典的一个案例莫过于重启服务时经常看到的一个脚本

#!/bin/bash
# 重启xx服务

ps -ef | grep application | grep -v grep | awk '{print $2}' | xargs kill -9
# 重启服务
nohup java -jar xxx.jar ...

在上面的一个脚本中我们使用了awk命令,也可以看懂这个命令的作用,至于到底是什么原理或者说为什么有这样的效果很多人是不清楚。反正大家都是这么写的,我要做的只是 copy copy 改~。那么今天开始我们将一起学习awk,其实awk远比你认知的要更为强大!

快速开始

例如有以下一个文件 employ.dat,文件包含员工姓名、每小时的工资、工作时长,每一行代表一个员工的记录

张三       25.00      0
李四       22.75      0
王五       19.00     10
赵六       30.00     20
钱七       42.50     22
王八       80.00     18

现在想要打印每个员工的姓名以及工资(时薪 * 工作时长),而且雇员的工作时长(第三列)必须大于0,这时候只需要下面的一行命令即可以完成上面的工作:

awk '$3 > 0 {print $1 ,$2 * $3}'  employ.dat

执行上面的命令后结果如下:

王五 190
赵六 600
钱七 935
王八 1440

通过输出的结果可以看出上面的命令已经很好的完成了我们的需求。
该行命令告诉操作系统运行 awk 程序, 被运行的程序用单引号包围起来, 从输入文件 emp.data 获取数据。单引号包围的部分是一个完整的 awk 程序. 它由一个单独的 模式–动作 语句 (pattern-action statement) 组成. 模式 $3 > 0 扫描每一个输入行, 如果该行的第三列 (或者说 字段 (field)) 大于零, 则动作

{print $1 ,$2 * $3}

再来一个需求,打印出工作时长为0的员工姓名,相信有了上面的例子,完成这个需求也很简单:

awk '$3 == 0 {print $1}'  employ.dat

AWK 程序的结构

在上面的命令行中, 被单引号包围的部分是使用 awk 语言编写的程序,每一个 awk 程序都是由一个或多个 模式–动作 语句组成的序列:

pattern { action }
pattern { action }
...

awk 的基本操作是在由输入行组成的序列中, 陆续地扫描每一行, 搜索可以被模式 匹配 (match) 的行.。“匹配”的精确含义依赖于问题中的模式, 比如, 对于 $3 > 0, 意味着 “条件为真”.。每一个输入行轮流被每一个模式测试. 每匹配一个模式, 对应的动作 (可能包含多个步骤) 就会执行。 然后下一行被读取, 匹配重新开始. 这个过程会一起持续到所有的输入被读取完毕为止。

运行 AWK 程序

运行一个 awk 程序有多种方式. 可以键入下面这种形式的命令
awk 'program' input files
这个命令对指定的输入文件的每一行, 执行 program. 例如你可以键入
awk '$3 == 0 { print $1 }' file1 file2

AWK的简单的输出

打印每一行

如果一个动作没有模式, 对于每一个输入行, 该动作都会被执行. 语句 print 会打印每一个当前输入行,
所以程序
{ print }
会将它所有的输入打印到标准输出. 因为 $0 表示一整行, 所以程序
{ print $0 }
完成同样的工作

打印某些字段

这种方式前面我们已经使用到了,例如打印第一列和第三列可以使用
{print $1, $3}

NF, 字段的数量

Awk 计算当前输入行的字段数量, 并将它存储在
一个内建的变量中, 这个变量叫作 NF (Number Of Field)。因此程序
{ print NF, $1, $NF }
将会打印每一个输入行的字段数量, 第一个字段, 以及最后一个字段。

打印行号

Awk 提供了另一个内建变量 NR (Number Of Record), 这个变量计算到目前为止, 读取到的行的数量. 我们可以使用 NR 和 $0为 employ.dat 的每一行加上行号:
awk '{ print NR, $0 }' employ.dat
输出就像这样:

1 张三       25.00      0
2 李四       22.75      0
3 王五       19.00     10
4 赵六       30.00     20
5 钱七       42.50     22
6 王八       80.00     18

将文本放入输出中

可以把单词放在字段与算术表达式之间:
awk '{ print "第",NR, "行记录是", $0 }' employ.dat

1 行记录是 张三       25.00      02 行记录是 李四       22.75      03 行记录是 王五       19.00     104 行记录是 赵六       30.00     205 行记录是 钱七       42.50     226 行记录是 王八       80.00     18

更精美的输

print 用于简单快速的输出. 如果读者想要格式化输出, 那么就需要使用 printf 语句。

字段排列

printf语句具有形式
printf(format, value1, value2, ... , valuen)
format 是一个字符串, 它包含按字面打印的文本, 中间散布着格式说明符, 格式说明符用于说明如何打印值。一个格式说明符是一个 %, 后面跟着几个字符, 这些字符控制一个 value 的输出格式. 第一个格式说明符说明value1 的输出格式, 第二个格式说明符说明 value2 的输出格式, 依次类推. 于是, 格式说明符的数量应该和被打印的 value 一样多。
这个程序使用 printf 打印每位员工的工资:
awk '{ printf(" %s 的工资是 %.2f元\n", $1, $2 * $3) }' employ.dat

 张三 的工资是 0.00元
 李四 的工资是 0.00元
 王五 的工资是 190.00元
 赵六 的工资是 600.00元
 钱七 的工资是 935.00元
 王八 的工资是 1440.00

BEGIN 与 END

特殊的模式 BEGIN 在第一个输入文件的第一行之前被匹配, END 在最后一个输入文件的最后一行被处理
之后匹配. 这个程序使用 BEGIN 打印一个标题:
awk 'BEGIN { print "姓名 时薪 工作时长"; print "" } { print }' employ.dat

姓名 时薪 工作时长

张三       25.00      0
李四       22.75      0
王五       19.00     10
赵六       30.00     20
钱七       42.50     22
王八       80.00     18

今天的内容就到这里了,欲知后事如何,请听下回分解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不务正业的攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值