awk一个神奇而又强大的功能,绝对是一个开发利器,效率直选!希望这里的一些总结能帮到那些存在困惑的人!
awk实战1-基础语法说明
awk实战2-流程控制语句总结
awk实战3-awk数组技巧
awk实战4-函数系列-算数函数说明
awk实战5-函数系列-基本字符串函数
awk实战6-函数系列-字符串函数说明-asort和sub
awk实战7-函数系列-时间函数
awk实战8-函数系列-字节操作
awk实战9-IO函数-getline和close
awk实战10-IO函数-其他介绍
awk实战11-进阶-10种awk有效应用实战
awk实战12-进阶-再谈awk匹配模式
awk处理小问题-解决局部jar包替换
文章目录
- awk函数-IO函数一getline和close
-
- 1 getline 概览
- 2 getline-关注指数:☆☆☆☆
- 3 getline
awk函数-IO函数一getline和close
最近两节内容主要介绍awk 关于io操作的一些函数,包括读取行\系统命令调用等,这是很重要的一部分awk函数! 由于getline是一个很有意思io函数,功能强大,细节也值得关注
,在本节单独讨论一下它以及一些常见用法!
1 getline 概览
getline用于获取下一行输入到$0,同时它支持设置一些内置变量,下面将getline的使用总结如下:
用法 | 官方说明 | 解释 |
---|---|---|
getline | Set $0 from next input record; set NF, NR, FNR, RT. | 读取下一行是把字符串传给$0,它会改变内置变量NR等值; |
getline <file | Set $0 from next record of file; set NF, RT. | 从文件读取一行; |
getline var | Set var from next input record; set NR, FNR, RT. | 读取下一行传给变量var; |
getline var <file | Set var from next record of file, RT. | 从文件读取一行传给变量var; |
command | getline var | Run command piping the output either into $0 or var, RT | 从管道传入一行给变量var; |
2 getline-关注指数:☆☆☆☆
如下用例可知getline后NR变成了4,但是
代码仍然会执行下一行操作
[email protected]:~$ seq 10 | awk '/3/{print "getline前:",NR,FNR,NF,$0; getline; print "getline后:",NR,FNR,NF,$0}/4/{print "getline后下次匹 配:",NR,FNR,NF,$0}'
getline前: 3 3 1 3
getline后: 4 4 1 4
getline后下次匹配: 4 4 1 4
3 getline <file-关注指数:☆☆☆☆
此次输入来自"/etc/hosts";可见
getline后
打印已经打印了输入文件的第一行;
[email protected]:~$ seq 10 | awk '/3/{print "getline前:",NR,FNR,NF,$0; getline <"/etc/hosts"; print "getline后:",NR,FNR,NF,$0}/4/{print "getline后下次匹配:",NR,FNR,NF,$0}'
getline前: 3 3 1 3
getline后: 3 3 2 127.0.0.1 localhost
getline后下次匹配: 4 4 1 4
4 getline var -关注指数:☆☆☆☆☆
相对于
getline <file
,可知$0不会在getline后变化,而是传入了变量a;
!!!!特别注意:getline var会导致awk的下一次匹配跳过已经查询的行4
—这里要特别与
getline区别
[email protected]:~$ seq 10 | awk '/3/{print "getline前:",NR,FNR,NF,$0; getline a; print "getline后:",NR,FNR,NF,$0,a}/4/{print "getline后下次匹配:",NR,FNR,NF,$0}'
getline前: 3 3 1 3
getline后: 4 4 1 3 4
5 getline var <file -关注指数:☆☆☆
与
getline var
对比 awk var值从/etc/hosts配置获得,此外下一次awk扫描,也会继续扫描已经在处理了的第三行;
[email protected]:~$ seq 10 | awk '/3/{print "getline前:",NR,FNR,NF,$0; getline a <"/etc/hosts"; print "getline后:",NR,FNR,NF,$0,a}/4/{print "getline后下次匹配:",NR,FNR,NF,$0}'
getline前: 3 3 1 3
getline后: 3 3 1 3 127.0.0.1 localhost
getline后下次匹配: 4 4 1 4
6 command | getline var -关注指数:☆☆☆
[email protected]:~$ seq 10 | awk '/3/{print "getline前:",NR,FNR,NF,$0; "ls -l | tail" | getline a; print "getline后:",NR,FNR,NF,$0,a}/4/{print "getline后下次匹配:",NR,FNR,NF,$0}'
getline前: 3 3 1 3
getline后: 3 3 1 3 drwxr-xr-x 2 user users 4096 7月 30 08:42 Documents
getline后下次匹配: 4 4 1 4
7 getline获取整个输出 -关注指数:☆☆☆☆☆☆
7.1 方案一:修改分隔符RS
回顾一下第一篇文章里说的内置变量RS的含义:
RS:当前的“记录分隔符”。默认状态下,输入的每行都被作为一个记录,因此默认记录分隔符是换行符。
输入每行的默认分隔符是换行符,我们只有把RS换成"",才可以将执行命令全部输出!
[email protected]:~$ awk 'BEGIN{RS="";"ls -l" | getline var;print var}'
total 56
drwxr-xr-x 2 user users 4096 7月 30 08:42 Desktop
drwxr-xr-x 2 user users 4096 7月 30 08:42 Documents
drwxr-xr-x 2 user users 4096 7月 30 08:42 Downloads
-rw-r--r-- 1 user users 8980 7月 30 08:41 examples.desktop
drwxr-xr-x 2 user users 4096 7月 30 08:42 Music
drwxr-xr-x 26 root root 4096 7月 30 10:57 MyLearningCache
drwxr-xr-x 2 user users 4096 7月 30 08:42 Pictures
drwxr-xr-x 2 user users 4096 7月 30 08:42 Public
drwxr-xr-x 2 user users 4096 7月 30 08:42 Templates
drwxr-xr-x 2 user users 4096 7月 30 08:42 Videos
drwxr-xr-x 2 user users 4096 7月 30 08:41 模板
7.2 方案二:while循环方式
使用while方式逐行读取内容,并进行打印;
[email protected]:~$ awk 'BEGIN{while("ls -l" | getline var) print var; print "\n-->the current var:"var}'
total 56
drwxr-xr-x 2 user users 4096 7月 30 08:42 Desktop
drwxr-xr-x 2 user users 4096 7月 30 08:42 Documents
drwxr-xr-x 2 user users 4096 7月 30 08:42 Downloads
-rw-r--r-- 1 user users 8980 7月 30 08:41 examples.desktop
drwxr-xr-x 2 user users 4096 7月 30 08:42 Music
drwxr-xr-x 26 root root 4096 7月 30 10:57 MyLearningCache
drwxr-xr-x 2 user users 4096 7月 30 08:42 Pictures
drwxr-xr-x 2 user users 4096 7月 30 08:42 Public
drwxr-xr-x 2 user users 4096 7月 30 08:42 Templates
drwxr-xr-x 2 user users 4096 7月 30 08:42 Videos
drwxr-xr-x 2 user users 4096 7月 30 08:41 模板
-->the current var:drwxr-xr-x 2 user users 4096 7月 30 08:41 模板
其他用例:
awk 'BEGIN{while( getline var <"/etc/hosts") print var; print "\n-->the current var:"var}'
7.3 方案对比
这里需要澄清一下 修改分隔符方式获取的是整个命令行结果返回字符串,传给一个变量,而while方式只是循环调用getline,只能打印所有输出,但是最终变量只会记录最后一行输出;
8 close -关注指数:☆☆☆☆☆☆
getline使用管道\读取文件都非常方便,但是close我们使用过程打开的文件和管道更加重要,如下所示官方文档中给出的close的说明:
close(file [, how]) Close file, pipe or co-process. The optional how should only be used when closing one end of a two-way
pipe to a co-process. It must be a string value, either "to" or "from" getline ;
下面先看看不使用close关闭的文件和管道如何打印:
准备数据如下:
[email protected]:~$ pwd
/home/user
[email protected]:~$ cat test
a b
c d
e f
不使用close的情形:
##### 1-文件不close,下次打开文件还是执行上次打开文件的下一行
[email protected]:~$ seq 5 |awk '/3/{getline var <"test";print var}/4/{getline var <"test";print var}'
a b
c d
##### 2-管道不close,还是执行管道上次结果下一行
[email protected]:~$ seq 5 |awk '/3/{"cat test" | getline var;print var}/4/{"cat test" | getline var;print var}'
a b
c d
使用close函数关闭文件或者管道
##### 1-使用close匹配后关闭文件,下次打开文件仍然读取第一行
[email protected]:~$ seq 5 |awk '/3/{getline var <"test";print var;close("test")}/4/{getline var <"test";print var}'
a b
a b
##### 1-管道执行命令也是一样,将执行命令close后下次执行仍然从第一行执行
[email protected]:~$ seq 5 |awk '/3/{"cat test" | getline var;print var;close("cat test")}/4/{"cat test" | getline var;print var}'
a b
a b
总结一下:
- 1-close关闭文件或者管道后,下次执行相同命令或者打开相同文件getline会从首行执行;
- 2-未关闭文件或者管道,则下次getline会记住上次文件或命令位置,执行下一行;
- 3-一个脚本执行过程中是否close是根据需求而定,如需执行完后下次读入重复内容则必须close,如果本身需求为记录,比如while打印,则不需要关闭!
一个特别用例说明:打开同一个文件,如果路径有区别,即使是同一个文件实际上可以看作开了两个管道,不会交叉,如下用例我们分别使用cat test 和cat ~/test打开相对路径和绝对路径的文件,在awk看来实际上是两个命令,不共用一个管道!
[email protected]:~$ seq 5 |awk '/3/{getline var <"test";print var}/4/{getline var <"~/test";print var}'
a b
a b
9 getline其他示例 -关注指数:☆☆☆☆
9.1 与ping结合
[email protected]:~$ awk 'BEGIN{while("ping -c 5 192.168.43.132" | getline var) print var; print "-------------->laset:\n",var}'
PING 192.168.43.132 (192.168.43.132) 56(84) bytes of data.
64 bytes from 192.168.43.132: icmp_seq=1 ttl=64 time=0.057 ms
64 bytes from 192.168.43.132: icmp_seq=2 ttl=64 time=0.066 ms
64 bytes from 192.168.43.132: icmp_seq=3 ttl=64 time=0.083 ms
64 bytes from 192.168.43.132: icmp_seq=4 ttl=64 time=0.078 ms
64 bytes from 192.168.43.132: icmp_seq=5 ttl=64 time=0.118 ms
--- 192.168.43.132 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4094ms
rtt min/avg/max/mdev = 0.057/0.080/0.118/0.022 ms
-------------->laset:
rtt min/avg/max/mdev = 0.057/0.080/0.118/0.022 ms