awk实战9-IO函数-getline和close

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 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 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,但是代码仍然会执行下一行操作

user@user:~$ 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

此次输入来自"/etc/hosts";可见getline后打印已经打印了输入文件的第一行;

user@user:~$ 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 ,可知$0不会在getline后变化,而是传入了变量a;

!!!!特别注意:getline var会导致awk的下一次匹配跳过已经查询的行4—这里要特别与getline区别

user@user:~$ 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

getline var对比 awk var值从/etc/hosts配置获得,此外下一次awk扫描,也会继续扫描已经在处理了的第三行;

user@user:~$ 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 -关注指数:☆☆☆

user@user:~$ 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换成"",才可以将执行命令全部输出!

user@user:~$ 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方式逐行读取内容,并进行打印;

user@user:~$ 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关闭的文件和管道如何打印:

准备数据如下:

user@user:~$ pwd
/home/user
user@user:~$ cat test
a b 
c d
e f

不使用close的情形:

##### 1-文件不close,下次打开文件还是执行上次打开文件的下一行
user@user:~$ seq 5 |awk '/3/{getline var <"test";print var}/4/{getline var <"test";print var}'
a b 
c d
##### 2-管道不close,还是执行管道上次结果下一行
user@user:~$ seq 5 |awk '/3/{"cat test" | getline var;print var}/4/{"cat test" | getline var;print var}'
a b 
c d

使用close函数关闭文件或者管道

##### 1-使用close匹配后关闭文件,下次打开文件仍然读取第一行
user@user:~$ seq 5 |awk '/3/{getline var <"test";print var;close("test")}/4/{getline var <"test";print var}'
a b 
a b
##### 1-管道执行命令也是一样,将执行命令close后下次执行仍然从第一行执行
user@user:~$ 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看来实际上是两个命令,不共用一个管道!

user@user:~$ seq 5 |awk '/3/{getline var <"test";print var}/4/{getline var <"~/test";print var}'
a b 
a b 

9 getline其他示例 -关注指数:☆☆☆☆

9.1 与ping结合

user@user:~$ 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

你可能感兴趣的:(awk实战,awk,io函数,getline,close)