AWK 杂项函数
这里的翻译有些错误,有些是内置的函数,有些是语句,也就是关键字。我统统将它们翻译成函数了...
捂脸~~~~~~~~~~~
关闭管道 close(expr)
函数 close(cmd, [read_or_write])
用于关闭已经打开的管道。
参数说明
参数 | 说明 |
---|---|
cmd | 要关闭的管道 |
read_or_write | 要关闭的管道方向,如果不传则默认关闭管道,如果为 to 则关闭输入管道 |
范例
下面的范例演示了如何使用 close
关闭一个已经打开的管道
[www.twle.cn]$ awk 'BEGIN { cmd = "tr [a-z] [A-Z]" print "hello, world !!!" |& cmd close(cmd, "to") cmd |& getline out print out; close(cmd); }'
运行以上 awk 命令,输出结果如下
HELLO, WORLD !!!
上面这段程序看起来是不是很迷茫 ??
这估计是我们见过的最为复杂的程序了,下面我们就一步一步来拆解吧!!!
-
第一行
cmd = "tr [a-z] [A-Z]
定义了一个系统命令,我们会使用这个命令开启一个 双向通讯管道 -
第二行
print "hello, world !!!" |& cmd
。我们先来看
|& cmd
,这句话的意思是使用|&
输出重定向运算符打开一个 双向通讯管道 连接当前 AWK 程序和刚刚定义的命令。然后
print "hello, world !!!" |& cmd
就是把print
函数的输出结果重定向到刚刚定义的 双向通讯管道。说的直白一点,就是
print
函数为tr
命令提供了输入。 -
第三行
close(cmd, "to")
用于关闭刚刚打开的 双向通讯管道 的输入进程。 -
第四行
cmd |& getline out
把tr
命令的执行结果使用管道运算符&|
重定向到getline
函数。getline 函数会把结果储存到out
变量中。 -
最后一行
close(cmd)
用于关闭刚刚打开的 双向通讯管道
删除数组元素 delete(arr)
AWK 中数组的那些默认操作,就是只管添加不管删。如果要删除数组中的某个元素,需要用到 delete
函数。
它的原型如下
delete arr[i]
参数
参数 | 说明 |
---|---|
arr[i] | 要删除的数组的元素 |
范例
下面的 awk 程序,演示了如何使用 delete 函数删除数组元素。
[www.twle.cn]$ awk 'BEGIN { arr[0] = "One" arr[1] = "Two" arr[2] = "Three" arr[3] = "Four" print "Array elements before delete operation:" for (i in arr) { print arr[i] } delete arr[0] delete arr[1] print "Array elements after delete operation:" for (i in arr) { print arr[i] } }'
运行以上 awk 命令,输出结果如下
Array elements before delete operation: One Two Three Four Array elements after delete operation: Three Four
退出程序 exit([expr])
函数 exit()
用于停止执行脚本。它之后的脚本就不再会执行了。
它的原型如下
exit [expr]
参数 expr
是可选的,它会成为 AWK 的返回值。
参数
参数 | 说明 |
---|---|
expr | 用于指定的 AWK 的返回值 |
范例
下面的程序,使用 exit
退出当前程序
[www.twle.cn]$ awk 'BEGIN { print "简单教程欢迎您" exit 10 print "这句永远不会被执行啦....." }'
简单教程欢迎您
刷新缓冲区 fflush([output-expr])
几乎所有的语言中,都或多或少存在 flush()
这个函数,也存在 刷新缓冲区 这个概念。
那 刷新缓冲区 是什么意思呢 ? 哈哈,很简单的,就是把 储存在内存中的数据保存到文件或者管道中。
一副,数据我给你保存了,断电了就不再关我啥事的~~~
函数 fflush()
用于刷新与打开的输出文件或管道关联的任何缓冲区
它的函数原型如下
fflush([output-expr])
参数说明
参数 | 说明 |
---|---|
output-expr | 要刷新的缓冲区 |
- 如果没有传递
output-expr
,那么默认刷新 标准输出。 - 如果传递的是 空字符串
''
,那么会刷新所有当前 awk 程序打开的文件或者管道。 - 否则,刷新指定的文件或管道。
范例
范例,等等我找找...
读取下一行 getline
经过前面的渲染,我们知道,AWK 是一个行文本处理器。AWK 会把输入的每一个行都经过 模式/处理程序。
如果我们要提前读取下一行,要怎么做呢?虽然我也不知道为啥会有这种需求,但,确实有这种需求啊。
不过还真别说,AWK 还真有个函数可以实现这种变态的需求,那就是 getline
函数 getline
怎么说呢,简单的说,它用于读取下一行,复杂的说
- 它会读取下一行,并进行分割并替代当前的 $0, $1。最直接的影响,就是输入缓存也会被迭代到下一行。
- 如果下一行不存在,也就是已经达到文件末尾,则什么都不做,也不会替换当前的 $0 $1 ...
哎呀,有点说不清楚,直接看范例吧。
它的函数原型如下
getline()
它既没有参数,也没有返回值,因此调用的时候可以直接输入 next
不用后面加括号。
范例
假设当前电脑上有个文件 employee.txt
,内容如下
employee.txt
1) 张三 技术部 23 2) 李四 人力部 22 3) 王五 行政部 23 4) 赵六 技术部 24 5) 朱七 客服部 23
下面的程序,使用 getline
读取下一行。
[www.twle.cn]$ awk '{getline; print $0}' employee.txt
运行以上 awk 命令,输出结果如下
2) 李四 人力部 22 4) 赵六 技术部 24 5) 朱七 客服部 23
是不是对输出结果有点难以理解?为啥第一行、第三行消失了。。。。。
我们来分析下程序
-
当程序开始执行第一行的时候,遇到
getline
,这时候不得不从输入缓存里读取下一行,也就是第二行,导致第一行的 $0,$1 ... 被第二行代替,因此print $0
直接输出了第二行。 -
print $0
执行完之后,开始进入下一个迭代,这时候因为第二行已经读取了,处于缓存头部的是第三行,然后又因为 getline 语句,导致了第四行的输出。 -
当开始第三个循环的时候,已经读取到第五行,这时候,当前的 $0 等等也就是第五行的数据。然后调用 getline ,因为已经到了文件末尾,getline 没有读取到数据,那就不会执行替换,$0,$1 ...还是之前那个,也就是第五行数据。
处理下一行 next()
经过前面的渲染,我们知道,AWK 是一个行文本处理器。AWK 会把输入的每一个行都经过 模式/处理程序。
那,如果我们不想处理当前行了,想直接进行下一行要怎么办呢?
因为不在 循环语句 中,所以 break
关键字失效啦。
为了应对这种情况,AWK 内置了 next()
函数用于处理下一行。
它的函数原型如下
next()
它既没有参数,也没有返回值,因此调用的时候可以直接输入 next
不用后面加括号。
范例
假设当前电脑上有个文件 employee.txt
,内容如下
employee.txt
1) 张三 技术部 23 2) 李四 人力部 22 3) 王五 行政部 23 4) 赵六 技术部 24 5) 朱七 客服部 23
下面的 AWK 命令,当处理到 王五 的时候直接略过,继续处理下一行
[www.twle.cn]$ awk '{if ($2 ~/王五/) next; print $0}' employee.txt
运行以上 awk 命令,输出结果如下
1) 张三 技术部 23 2) 李四 人力部 22 4) 赵六 技术部 24 5) 朱七 客服部 23
处理下一个文件 nextfile
AWK 是可以处理多个文件的。那么当我们不想处理当前文件,想直接处理下一个文件了要怎么办呢 ?
答案就是: 使用 nextfile() 函数
函数 nextfile() 用于跳过当前文件的处理,直接进入下一个文件处理。
nextfile() 函数会改变程序的执行流程。确切的说,是 停止处理当前的输入文件,直接处理下一个文件,从下一个文件的第一行开始重新循环执行 模式/处理程序。
函数 nextfile() 的原型为
nextfile()
它既没有参数,也没有返回值,因此调用的时候可以直接输入 nextfile
不用后面加括号。
范例
假设当前电脑上有两个文件,employee.txt
和 employee1.txt
,两个文件的内容如下
employee.txt
1) 张三 技术部 23 2) 李四 人力部 22 3) 王五 行政部 23 4) 赵六 技术部 24 5) 朱七 客服部 23
employee1.txt
6) 小红 技术部 28 7) 小李 人力部 29 8) 小王 行政部 33 9) 小花 销售部 32 10) 小山 客服部 25
下面的 AWK 命令,当处理到 王五 的时候直接跳过当前文件执行,继续执行下一个文件。
[www.twle.cn]$ awk '{ if ($2 ~ /王五/) nextfile; print $0 }' employee.txt employee1.txt
运行以上 awk 命令,输出结果如下
1) 张三 技术部 23 2) 李四 人力部 22 6) 小红 技术部 28 7) 小李 人力部 29 8) 小王 行政部 33 9) 小花 销售部 32 10) 小山 客服部 25
函数返回值 return(expr)
AWK 中的 return
竟然是一个函数,我去,而不是关键字~~~~~。
函数 return(expr)
用于在用户自定义的函数中返回一个值。
它的原型如下
return(expr)
函数 return(expr)
用于在用户自定义的函数中计算 expr
表达式的结果并将结果作为函数的返回值。
注意
与其它语言不同:
- AWK 中的
return
是函数而不是关键字- 另一方面,如果没有传递
expr
,那么return
返回的结果是未定义的。
参数说明
参数 | 说明 |
---|---|
expr | 要返回的表达式 |
范例
我们首先在当前目录下创建一个文件 fns.awk
然后输入以下 AWK 命令
function msadd(num1, num2) { result = num1 + num2 return result } BEGIN { res = msadd(15, 27) print "15 + 27 = " res }
使用 awk -f fns.awk
运行上面的 awk 命令,输出结果如下
15 + 27 = 42
执行系统脚本命令 system(command)
函数 system(command)
用于执行系统脚本命令,并返回脚本执行的退出状态。
它的原型如下
system(command)
函数 system(command)
用于执行系统脚本命令 command
,并返回脚本执行的退出状态。
退出状态分为以下几种:
- 返回状态
0
表示命令执行成功 - 非零值表示命令执行失败
参数说明
参数 | 说明 |
---|---|
command | 要执行的脚本命令 |
范例
以下示例显示当前日期,并显示该命令的返回状态
[www.twle.cn]$ awk 'BEGIN { ret = system("date"); print "返回值为 = " ret }'
运行上面的 awk 命令,输出结果如下
2019年 05月 31日 星期五 23:39:29 CST 返回值为 = 0