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

awk内置变量之FNR/NR、FS/OFS、NF、ORS/RS

2017-11-03 21:33 399 查看
awk有一些内置的变量,本文主要讲述与 行分割符、列分割符、行号、列号有关的变量

本文用到的测试文件如下:

qingsong@db2a:~$ cat ipa.txt
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet addr:192.168.16.128 Bcast:192.168.16.255 Mask:255.255.255.0
inet addr:127.0.0.1 Mask:255.0.0.0
qingsong@db2a:~$ cat ipb.txt
Beth 4.00 0
Dan 3.75 0
Kathy 4.00 10
Mark 5.00 20
Mary 5.50 22
Susie 4.25 18


1. FNR 与 NR (行号相关)

说明如下:

FNR
current record number in FILENAME.
NR current record number in the total input stream.

FNR表示该记录在其对应文件中的行号, NR表示该记录在整个input stream中的行号。

如果只有一个文件,两者是一样的。如果是多个文件,则每读取一个新的文件时,FNR都会被重置为1,而NR一直增加。

下面两条命令中,第一条用于打印每一行的FNR和内容,第二条用于打印每一行的NR和内容:
qingsong@db2a:~$ awk '{print FNR, $0}' ipa.txt ipb.txt
1 inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
2 inet addr:192.168.16.128  Bcast:192.168.16.255  Mask:255.255.255.0
3 inet addr:127.0.0.1  Mask:255.0.0.0
1 Beth  4.00    0
2 Dan   3.75    0
3 Kathy 4.00    10
4 Mark  5.00    20
5 Mary  5.50    22
6 Susie 4.25    18
qingsong@db2a:~$ awk '{print NR, $0}' ipa.txt ipb.txt
1 inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
2 inet addr:192.168.16.128  Bcast:192.168.16.255  Mask:255.255.255.0
3 inet addr:127.0.0.1  Mask:255.0.0.0
4 Beth  4.00    0
5 Dan   3.75    0
6 Kathy 4.00    10
7 Mark  5.00    20
8 Mary  5.50    22
9 Susie 4.25    18


2. FS 与 OFS (列分割符)

FS
splits records into fields as a regular expression.
OFS inserted between fields on output, initially = " ".

FS 表示field分割符,也就是输入中 列的分割符,默认为空格或Tab。 OFS表示输出多个列的时候,列与列之间的分割符,默认为一个空格。

下面的命令打印ipb.txt的第1列和第2列,使用的默认的分割符:
qingsong@db2a:~$ awk '{print $1,$2}' ipb.txt
Beth 4.00
Dan 3.75
Kathy 4.00
Mark 5.00
Mary 5.50
Susie 4.25


将OFS设为冒号,表示输出中用冒号作分割符,效果如下:
qingsong@db2a:~$ awk 'BEGIN {OFS = ":"} {print $1, $2}' ipb.txt
Beth:4.00
Dan:3.75
Kathy:4.00
Mark:5.00
Mary:5.50
Susie:4.25

如果将FS设置为".", 则读取输入的时候,读到"."才认为是一列,下面是打印ipb.txt第一列:
qingsong@db2a:~$ awk 'BEGIN {FS = "."} {print $1}' ipb.txt
Beth    4
Dan     3
Kathy   4
Mark    5
Mary    5
Susie   4

3. NF (列号相关)

NF number of fields in the current record.

NF 表示当前行一共有多少列,而非列号,假设有以下文本

qingsong@db2a:~$ cat ipc.txt

hello, world

this is a

sample text of awk

打印每一行有多少列

qingsong@db2a:~$ awk '{print NF}' ipc.txt

2

3

4

打印倒数第2列和最后1列:

qingsong@db2a:~$ awk '{print $(NF-1), $NF}' ipc.txt

hello, world

is a

of awk

4. ORS与RS (行分割符)

ORS
terminates each record on output, initially = "\n".
RS input record separator, initially = "\n".

RS 表示输入文件中行分割符,默认是一个"\n",

ORS表示输出中,行与行之间的分割符,默认是一个"\n"

以ipc.txt为例子,默认awk使用"\n"作为输出的记录分隔符,可以使用ORS改变这一行为,例如下面的命令使用"#"作为输出行分割符:

qingsong@db2a:~$ awk 'BEGIN { ORS = "#" } {print}' ipc.txt

hello, world#this is a #sample text of awk#qingsong@db2a:~$

比如有下面的文件:

qingsong@db2a:~$ cat ipd.txt

if (a > b);return a;else;return b

直观看起来只有一条记录(一行),但如果把分号当作输入的记录分割符,则有4条记录,下面是打印前3条记录

qingsong@db2a:~$ awk 'BEGIN { RS = ";" } NR <= 3 {print}' ipd.txt

if (a > b)

return a

else
qingsong@db2a:~$

关于ORS/RS的应用,我之前写过另一篇文章,如下:

Linux: 文本查找包含某个关键字的段落(awk实现)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  AWK shell 内置变量