本文示例文本
~]$ cat a.txt
ID name gender age email phone
1 Bob male 28 abc@qq.com 18023394012
2 Alice female 24 def@gmail.com 18084925203
3 Tony male 21 aaa@163.com 17048792503
4 Kevin male 21 bbb@189.com 17023929033
5 Alex male 18 ccc@xyz.com 18185904230
6 Andy female 22 ddd@139.com 18923902352
7 Jerry female 25 exdsa@189.com 18785234906
8 Peter male 20 bax@qq.com 17729348758
9 Steven female 23 bc@sohu.com 15947893212
10 Bruce female 27 bcbd@139.com 13942943905
作用:
getline主要用于读取需要被处理的内容
工作方式:
读取下一行之后,继续执行getline后面的代码
数据源:
getline可以从标准输入,非选项型文件,另外还可以通过重定向的方式获取数据
返回值:
getline在读取数据时,会自动返回一个整数值,包括0,正负数
- 如果getline可以获取到数据,则返回1(比如读取一个非空文件)
- 如果遇到
EOF
,则返回0(文件读取到最后一行,或者从标准输入收到EOF
) - 如果遇到错误,则会返回负值(-1表示文件无法打开,-2表示需要重试,同时还会用变量来描述错误)
对输入内容的判断
由于getline读取数据源时可能会出现问题,因此需要对getline的数据源进行判断,从而便于排错:
if((getline < "filename") >0){...} ##文件名需要用双引号包围,否则报错
if((getline) <= 0){...}
if((getline) < 0 ){...}
getline数据处理顺序问题
getline是读取当前行的下一行,然后交给后续代码处理:
getline是处于awk的main代码块中,如果放在BEGIN或END代码块中则不能发挥其功能
1.放在main代码块中
~]$ awk '{if((getline) > 0 ){print $0}}' a.txt ##这样的话就能读取偶数行
读取奇数行:
~]$ awk 'NR>=2{if((getline) > 0){print $0}}' a.txt
2.放在BEGIN代码块
~]$ awk 'BEGIN{while((getline) > 0){print $0}}' a.txt ##这样能全部读取
3.放在END代码块
因为END代码块是在文件处理完成之后才执行,因此此时getline已没有数据源了,因此这时getline是不生效的
`注意:getline放在main代码段和BEGIN代码段中的输出是有区别的
~]$ awk 'BEGIN{while((getline) > 0){print $0}}' a.txt ##输出全文,因为在BEGIN代码块中读取了一条记录才会进入main代码块
~]$ awk '{while((getline) > 0){print $0}}' a.txt #第一行会被getline跳过
`
无参数的getline
getline无参数时,表示读取下一条记录并保存到$0中,并且会继续执行后续的代码逻辑,并且进行字段分割,然后继续执行后续的代码逻辑 此时的getline会设置NR,FNR,$0和$N
~]$ cat test.txt
1-2-3-4-5
2-3-4-5-6
3-4-5-6-1
4-5-6-1-2
5-6-1-2-3
6-1-2-3-4
~]$ awk -F '-' '{while((getline) > 0 ){print $1}}' test.txt ##默认会跳过第一行
2
3
4
5
6
~]$ awk -F '-' 'BEGIN{while((getline) > 0 ){print NF}}' test.txt
5
5
5
5
5
5
~]$ awk -F '-' 'BEGIN{while((getline) > 0 ){print NR}}' test.txt
1
2
3
4
5
6
~]$ awk -F '-' 'BEGIN{while((getline) > 0 ){print FNR}}' test.txt
1
2
3
4
5
6
一个参数的getline
一个参数的getline在读取记录时,会将下一条记录放在变量中,并且不会对其分割
~]$ awk '{if((getline var1) <= 0){exit}{print var1}{print $0}}' a.txt
1 Bob male 28 abc@qq.com 18023394012
ID name gender age email phone
3 Tony male 21 aaa@163.com 17048792503
2 Alice female 24 def@gmail.com 18084925203
5 Alex male 18 ccc@xyz.com 18185904230
4 Kevin male 21 bbb@189.com 17023929033
7 Jerry female 25 exdsa@189.com 18785234906
6 Andy female 22 ddd@139.com 18923902352
9 Steven female 23 bc@sohu.com 15947893212
8 Peter male 20 bax@qq.com 17729348758
~]$ awk '/^1/{while((getline var1) <= 0){exit}{print var1}{print $0}}' a.txt
2 Alice female 24 def@gmail.com 18084925203
1 Bob male 28 abc@qq.com 18023394012
从指定的文件读取数据
- getline < filename #从文件读取数据,并且读取的数据会保存至$0中,会设置 0 , 0, 0,N,NF
- getline var < filename #从文件读取数据保存至变量var中,不划分字段不设置变量
~]$ cat test.txt
1-2-3-4-5
2-3-4-5-6
3-4-5-6-1
4-5-6-1-2
5-6-1-2-3
6-1-2-3-4
~]$ awk '{if((getline < "test.txt") > 0){print}}' a.txt ##读取到文件a.txt的第一条记录时就读取test.txt的所有内容
~]$ awk '{while((getline < "test.txt") > 0){print}}' a.txt ##也是读取到a.txt的第一条记录就读取了test.txt的所有内容
`注意:`关闭文件与不关闭文件的区别,不关闭文件的话,读取到a.txt的第一行就读取完了test.txt的内容,并且test.txt的文件指针一直在文件末尾,
因此在循环读取a.txt的后续记录时,输出的test.txt的内容都是空的,因为偏移指针在文件末尾,读取时直接收到EOF而结束读取,因此test.txt
只会被输出一次
~]$ awk '{while((getline < "test.txt") > 0){print};close("test.txt")}' a.txt
使用close("test.txt")关闭文件后,后续的每次循环都会输出一次test.txt文件的所有行,因此会有66(6*11)行输出
从shell命令中读取数据
- cmd | getline # 无参数读取数据,读取的数据将会被放入$0,会进行变量划分 0 , 0, 0,N,NF
- cmd | getline var1 #一个参数的getline,将读取的数据存放在变量var1中,不设置变量
~]$ awk '{while(("seq -w 01 05" | getline var1 ) > 0){print var1};close("seq -w 01 05")}' test.txt ##这样就会输出6次1~5,
总共30行
~]$ cat get_num.awk
#!/usr/bin/awk -f
{
while(("seq -w 01 05" | getline var1) > 0){
print var1
}
close("seq -w 01 05")
}
~]$ chmod +x get_num.awk
~]$ ./get_num.awk test.txt ##这样运行与上面的命令行模式是一样的
~]$ awk '{if(("date +\"%F %T\"" | getline var1) >0 );print var1;close(get_date)}' a.txt ##输出时间