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

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实现)

你可能感兴趣的:(LINUX,shell)