天天看点

awk实战9-IO函数-getline和closeawk函数-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 <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