windows ubuntu sed,awk,grep:9.awk 内置变量

本文详细解释了awk工具中关键变量FS(输入字段分隔符)、OFS(输出字段分隔符)、RS(记录分隔符)和NR/FNR的作用,以及如何处理多字段分隔和记录计数。通过实例展示了这些概念在实际操作中的应用。
摘要由CSDN通过智能技术生成

目录

55. FS –输入字段分隔符

56. OFS – 输出字段分隔符

57. RS – 记录分隔符

58. ORS – 输出记录分隔符

59. NR – 记录序号

60. FILENAME – 当前处理的文件名

61. FNR – 文件中的 NR


55. FS –输入字段分隔符

awk 默认的字段分隔符是空格,如果你的输入文件中不是一个空格作为字段分隔符,
你已经知道可以在 awk 命令行上使用 -F 选项来指定它 :
awk –F ‘,’ ‘{print $2,$3}’ employee.txt
同样的事情,也可以使用 awk 内置变量 FS 来完成。 FS 只能在 BEGIN 区域中使用。
awk ‘BEGIN {FS=”,”} {print $2,$3}’ employee.txt
BEGIN 区域可以包含多个命令,下面的例子中, BEGIN 区域包含一个 FS 和一个 print 命令 .BEGIN
区域的多个命令之间,要用分号分隔。
$awk 'BEGIN { FS=",";\
> print "---------------------------\nName\tTitle\n------------------------"}\
> {print $2,"\t",$3;}\
> END {print "-----------------------------------------"}' employee.txt
---------------------------
Name Title
------------------------
John Doe CEO
Jason Smith IT Manager
Raj Reddy Sysadmin
Anand Ram Developer
Jane Miller Sales Manager
-----------------------------------------
注意:默认的字段分隔符不仅仅是单个空格字符,它实际上是一个或多个空白字符。
下面的 employee-multiple-fs.txt 文件,每行记录都包含 3 个不同的字段分隔符 :
z , 雇员 id 后面的分隔符是逗号
z : 雇员姓名后面的分隔符是分号
z % 雇员职位后面的分隔符是百分号
创建文件 :
$vi employee-multiple-fs.txt
101,John Doe:CEO%10000
102,Jason Smith:IT Manager%5000
103,Raj Reddy:Sysadmin%4500
104,Anand Ram:Developer%4500
105,Jane Miller:Sales Manager%3000 当遇到一个包含多个字段分隔符的文件时,不必担心, FS 可以搞定。你可以使用正则表达
式来指定多个字段分隔符,如 FS = “[,:%]” 指定字段分隔符可以是逗号 , 或者分号 : 或者百
分号 %
因此,下面的例子将打印 employee-multiple-fs.txt 文件中雇员名称和职位 .
$awk 'BEGIN {FS="[,:%]"}{print $2,$3}' employee-multiple-fs.txt
John Doe CEO
Jason Smith IT Manager
Raj Reddy Sysadmin
Anand Ram Developer
Jane Miller Sales Manager

56. OFS – 输出字段分隔符

FS 是输入字段分隔符, OFS 是输出字段分隔符。 OFS 会被打印在输出行的连续的字段之间。
默认情况下, awk 在输出字段中间以空格分开。
请注意,我们没有指定 IFS 作为输入字段分隔符,我们从简地使用 FS
下面的例子打印雇员姓名和薪水,并以空格分开。当你使用单个 print 语句打印多个以逗号
分开 ( 如下面的例子所示 ) 的变量是,每个变量之间会以空格分开。

$awk -F ',' '{print $2,$3}' employee.txt

John Doe CEO
Jason Smith IT Manager
Raj Reddy Sysadmin
Anand Ram Developer
Jane Miller Sales Manager
如果你尝试认为地在输出字段之间加上冒号,会有如下输出。请注意在冒号前后均有一个多
余的空格,这是因为 awk 仍然以空格作为输出字段分隔符。
下面的 print 语句实际上会打印 3 个值 ( 以逗号分割 ) —— $2,: $4. 因为如你所知,当使用单个
print 语句打印多个变量时,输出内容会包含多余的空格。

$awk -F ',' '{print $2,":",$3}' employee.txt

John Doe : CEO
Jason Smith : IT Manager
Raj Reddy : Sysadmin
Anand Ram : Developer
Jane Miller : Sales Manager
正确的方法是使用 awk 内置变量 OFS( 输出字段分隔符 ) ,如下面了示例。请注意这个例子中
分号前后没有多余的空格,因为 OFS 使用冒号取代了 awk 默认的分隔符。
下面的 print 语句打印两个变量 ($2 $4) ,使用都会分隔,然而输出结果却是以分号分隔 (
不是空格 ), 因为 OFS 被设置成了分号 .
$awk -F ',' 'BEGIN {OFS=":"} {print $2,$3}' employee.txt
John Doe:CEO
Jason Smith:IT Manager
Raj Reddy:Sysadmin
Anand Ram:Developer
Jane Miller:Sales Manager
同时请注意在 print 语句中使用和不使用逗号的细微差别 ( 打印多个变量时 ). 当在 print 语句中
指定了逗号, awk 会使用 OFS 。如下面的例子所示,默认的 OFS 会被使用,所以你会看到输
出值之间的空格。
$awk 'BEGIN { print "test1","test2"}'
test1 test2
不使用逗号是, awk 将不会使用 OFS ,其输出变量之间没有任何空格。
$awk 'BEGIN { print "test1" "test2"}'
test1test2

57. RS – 记录分隔符

假定有下面一个文件,雇员的 id 和名称都在单一的一行内 .
$vi employee-one-line.txt
101,John Doe:102,Jason Smith:103,Raj Reddy:104,Anand Ram:105,Jane, Miller
这个文件中,每条记录包含两个字段 (empid name), 并且每条记录以分红分隔 ( 取代了换行
). 每条记录中的单独的字段 (empid name) 以逗号分隔。
Awk 默认的记录分隔符是换行符。如果要尝试只打印雇员姓名,下面的例子无法完成:
$awk -F, '{print $2}' employee-one-line.txt
John Doe:102
这个例子把 employee-one-line.txt 的内容作为单独一行,把逗号作为字段分隔符,所以,它
打印 ”John Doe:102 作为第二个字段。
如果要把文件内容作为 5 行记录来处理 ( 而不是单独的一行 ) ,并且打印每条记录中雇员的姓
名,就必须把记录分隔符指定为分号,如下所示:
$awk -F, 'BEGIN { RS=":" } {print $2}' employee-one-line.txt
John Doe
Jason Smith
Raj Reddy
Anand Ram
Jane Miller
假设有下面的文件,记录之间用-分隔,独占一行。所有的字段都占单独的一行。
$vi employee-change-fs-ofs.txt
101
John Doe
CEO -
102
Jason Smith
IT Manager
-
103
Raj Reddy
Sysadmin
-
104
Anand Ram
Developer
-
105
Jane Miller
Sales Manager
上面例子中,字段分隔符 FS 是换行符,记录分隔符 RS ”-“ 和换行符。所以如果要打印雇员
名称和职位,需要:
$awk 'BEGIN{RS="-\n";FS="\n";OFS=":"}{print $2,$3}' employee-change-fs-ofs.txt
John Doe:CEO
Jason Smith:IT Manager
Raj Reddy:Sysadmin
Anand Ram:Developer
Jane Miller:Sales Manager

58. ORS – 输出记录分隔符

RS 是输入字段分隔符, ORS 是输出字段分隔符。请注意,我们没有指定 IFS 作为输入字段分
隔符,我们从简地使用 FS
下面的例子在每个输出行后面追加 ”---------“.awk 默认使用换行符 ”\n” 作为 ORS ,这个例子中,
我们使用”\n---\”作为 ORS
$ awk 'BEGIN {FS=",";ORS="\n---\n"} {print $2,$3}' employee.txt
John Doe CEO
---
Jason Smith IT Manager
---
Raj Reddy Sysadmin
---
Anand Ram Developer
---
Jane Miller Sales Manager ---
下面的例子从 employee.txt 获取输入,把每个字段打印成单独一行,每条记录用”---“分隔
$ awk 'BEGIN { FS=",";OFS="\n";ORS="\n---\n"}{print $1,$2,$3}' employee.txt
101
John Doe
CEO
---
102
Jason Smith
IT Manager
---
103
Raj Reddy
Sysadmin
---
104
Anand Ram
Developer
---
105
Jane Miller
Sales Manager
---

59. NR – 记录序号

NR 非常有用,在循环内部标识记录序号。用于 END 区域时,代表输入文件的总记录数。
尽管你会认为 NR 代表 记录的数量 (Number of Records)” ,但它跟确切的叫法是 记录的序号
(Number of the Record)”, 也就是当前记录在所有记录中的行号。
下面的例子演示了 NR block END 区域是怎么运行的:
$ awk 'BEGIN {FS=","} \
> {print "Emp Id of record number",NR,"is",$1;}\
> END {print "Total number of records:",NR}' employee.txt
Emp Id of record number 1 is 101
Emp Id of record number 2 is 102
Emp Id of record number 3 is 103
Emp Id of record number 4 is 104
Emp Id of record number 5 is 105
Total number of records: 5

60. FILENAME – 当前处理的文件名

当使用 awk 处理多个输入文件时, FILENAME 就显得很有用,它代表 awk 当前正在处理的文
件。
$ awk '{ print FILENAME }' \
> employee.txt employee-multiple-fs.txt
employee.txt
employee.txt
employee.txt
employee.txt
employee.txt
employee-multiple-fs.txt
employee-multiple-fs.txt
employee-multiple-fs.txt
employee-multiple-fs.txt
employee-multiple-fs.txt
如果 awk 从标准输入获取内容, FILENAME 的值将会是 ”-“ ,下面的例中,我们不ᨀ供任何输
入文件,所以你应该手动输入内容以代替标准输入。
下面的例子中,我们只输入一个人名 ”John Doe” 作为第一条记录 , 然后 awk 打印出该人的姓氏。
这种情况下,必须按 Ctrl-C 才能停止标准输入。
$ awk '{print "Last name:",$2;\
> print "Filename:",FILENAME}'
John Deo
Last name: Deo
Filename: -
上面这个例子在使用管道向 awk 传递数据时,同样适用。如下所示,打印出来的 FILENAME
仍然是 ”-“
$ echo "Johe Doe" | awk '{print "Last name:",$2;\
> print "Filename:",FILENAME}'
Last name: Doe
Filename: -
注意 : BEGIN 区域内, FILENAME 的值是空,因为 BEGIN 区域只针对 awk 本身,而不处理任
何文件。

61. FNR – 文件中的 NR

我们已经知道 NR 记录条数 ”( 或者叫 记录的序号 ”), 代表 awk 当前处理的记录的行号。 在给 awk 传递了两个输入文件时 NR 会是什么? NR 会在多个文件中持续增加,当处理到第
二个文件时, NR 不会被重置为 1 ,而是在前一个文件的 NR 基础上继续增加。
下面的例子中,第一个文件有 5 条记录,第二个文件也有 5 条记录。如下所示,当 body
域的循环处理到第二个文件时, NR 6 开始递增 ( 而不是 1). 最后在 END 区域, NR 返回两个
文件的总记录条数。
$ awk 'BEGIN {FS=","}\
> {print FILENAME ": record number",NR,"is",$1;} \
> END {print "Total number of records:",NR}' \
> employee.txt employee-multiple-fs.txt
employee.txt: record number 1 is 101
employee.txt: record number 2 is 102
employee.txt: record number 3 is 103
employee.txt: record number 4 is 104
employee.txt: record number 5 is 105
employee-multiple-fs.txt: record number 6 is 101
employee-multiple-fs.txt: record number 7 is 102
employee-multiple-fs.txt: record number 8 is 103
employee-multiple-fs.txt: record number 9 is 104
employee-multiple-fs.txt: record number 10 is 105
Total number of records: 10
下面例子同时打印 NR FNR:
$ awk -f fnr.awk employee.txt employee-multiple-fs.txt
FILENAME=employee.txt NR=1 FNR=1
FILENAME=employee.txt NR=2 FNR=2
FILENAME=employee.txt NR=3 FNR=3
FILENAME=employee.txt NR=4 FNR=4
FILENAME=employee.txt NR=5 FNR=5
FILENAME=employee-multiple-fs.txt NR=6 FNR=1
FILENAME=employee-multiple-fs.txt NR=7 FNR=2
FILENAME=employee-multiple-fs.txt NR=8 FNR=3
FILENAME=employee-multiple-fs.txt NR=9 FNR=4
FILENAME=employee-multiple-fs.txt NR=10 FNR=5
END Block:NR=10 FNR=5

资料来源于《SedandAwk101Hacks》,大家有兴趣可以买一本,也可以关注我,我更新完它。

曾经,我花费大半月将它们跑完,现在啥都忘了,还是要常用。

只为学习交流,不为获利,侵权联系立删。

  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值