awk基础使用

 linux
 

awk 是处理文本文件的一个工具程序,目前主流 Linux 系统都自带这个工具程序。其主要功能是依次处理文件的每一行,并读取里面的每一个字段,对于处理服务器上的文本或者日志文件是非常方便的。但是它并不仅仅是一个工具程序,更是一门变成语言,本文记录一下日常用法,当做一个备忘。

一、基础用法

awk的基本用法就是下面的形式。

1
awk 动作 文件名

首先创建一个用于测试的文件,名字叫做test.txt,内容如下所示:

1
this is a test content

1、使用awk把文件的内容完全打印出来:

1
awk '{print $0}' test.txt # this is a test content

test.txt是awk所要处理的文本文件。前面单引号内部有一个大括号,里面就是每一行的处理动作print $0。其中,print是打印命令,$0代表当前行,因此上面命令的执行结果,就是把每一行原样打印出来。

2、输出每行的某个字段:

1
awk '{print $4}' test.txt # test

awk会根据空格和制表符,将每一行分成若干字段,依次用$1、$2、$3代表第一个字段、第二个字段、第三个字段等等。

为了方便后面的演示,准备一下test.txt的内容,直接把/etc/passwd文件的部分内容拷贝过来,得到test.txt的内容如下:

1
2
3
4
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
vagrant:x:1000:1000::/home/vagrant:/bin/bash

这个文件的字段分隔符是冒号(:),所以要用-F参数指定分隔符为冒号。然后,对每行的内容进行分段。

1
2
3
4
5
awk -F ':' '{print $1}' test.txt
# root
# bin
# daemon
# vagrant

二、变量

除了$ + 数字表示某个字段,awk还提供其他一些变量。

1、NF

变量NF表示当前行有多少个字段,因此$NF就代表最后一个字段,$(NF-1)代表倒数第二个字段。

1
2
3
4
5
6
7
8
9
10
awk -F ':' '{print $NF}' test.txt
# /bin/bash
# /sbin/nologin
# /sbin/nologin
# /bin/bash
awk -F ':' '{print $(NF-1)}' test.txt
# /root
# /bin
# /sbin
# /home/vagrant

2、NR

变量NR表示当前处理的是第几行。

1
2
3
4
5
6
7
8
9
10
11
awk -F ':' '{print NR}' test.txt
# 1
# 2
# 3
# 4

awk -F ':' '{print "row"NR ,"col6",$(NF-1)}' test.txt
# row1 col6 /root
# row2 col6 /bin
# row3 col6 /sbin
# row4 col6 /home/vagrant

上面代码中,print命令里面,如果原样输出字符,要放在双引号里面。如果要使用空格连接多个输出文本使用英文的逗号(,)。

三、函数

awk还提供了一些内置函数,方便对原始数据的处理。完整的函数列表参见:https://www.gnu.org/software/gawk/manual/html_node/Built_002din.html#Built_002din

使用示例:

1
2
3
4
5
awk -F ':' '{print toupper($7)}' test.txt
# /BIN/BASH
# /SBIN/NOLOGIN
# /SBIN/NOLOGIN
# /BIN/BASH

四、条件

awk允许指定输出条件,只输出符合条件的行。输出条件要写在动作的前面,如下所示:

1
awk '条件 动作' 文件名

示例1:

1
2
3
awk -F ':' '/sbin/ {print $0}' test.txt
# bin:x:1:1:bin:/bin:/sbin/nologin
# daemon:x:2:2:daemon:/sbin:/sbin/nologin

上面代码中,print命令前面是一个正则表达式,只输出包含sbin的行。

示例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
### 输出奇数行
awk -F ':' 'NR % 2 == 1 {print $0}' test.txt
# root:x:0:0:root:/root:/bin/bash
# daemon:x:2:2:daemon:/sbin:/sbin/nologin

### 输出第三行以后的行
awk -F ':' 'NR >3 {print $0}' test.txt
# vagrant:x:1000:1000::/home/vagrant:/bin/bash

### 输出第一个字段等于root的行
awk -F ':' '$1 == "root" {print $0}' test.txt
# root:x:0:0:root:/root:/bin/bash

### 输出第一个字段等于root或者vagrant的行
awk -F ':' '$1 == "root" || $1 == "vagrant" {print $0}' test.txt
# root:x:0:0:root:/root:/bin/bash
# vagrant:x:1000:1000::/home/vagrant:/bin/bash

五、if 语句

awk提供了if结构,用于编写复杂的条件。

只存在if条件的示例:如果第一段的值为vagrant,则输出整行。

1
2
awk -F ':' '{if ($1 == "vagrant") print $0}' test.txt
# vagrant:x:1000:1000::/home/vagrant:/bin/bash

if和else的示例:如果第一段的值为vagrant则输出整行,否则输出nothing。

1
2
3
4
5
awk -F ':' '{if ($1 == "vagrant") print $0;else print "nothing"}' test.txt
# nothing
# nothing
# nothing
# vagrant:x:1000:1000::/home/vagrant:/bin/bash

文章参考自:http://www.ruanyifeng.com/blog/2018/11/awk.html