5
年前我写过一篇文章:你用对awk了吗?,介绍了基于illumos
的发行版OmniOS
默认使用的awk
是非常旧的oawk
,很多功能都不支持。今天,illumos
终于更新了默认awk
,使其变成了nawk
(oawk
依然保留)。详情可查看这里:FLAG DAY: awk(1) is now nawk(1), oawk(1) is just oawk(1)。
标签:awk
awk打印文件的每一行
awk `1` input-file
上面awk
命令打印出输入文件的每一行。因为对每一个'/pattern/{action}'
,如果省略{action}
,则{action}
等价于{print}
,没有参数的print
会打印整个行。所以上述命令变成:
awk `1{print}` input-file
1
相当于永远为true
。因此会打印文件的每一行。举例如下:
# cat employee.txt
101,John Doe,CEO
102,Jason Smith,IT Manager
# awk '1' employee.txt
101,John Doe,CEO
102,Jason Smith,IT Manager
参考资料:
Awk One-Liners Explained, Part I: File Spacing, Numbering and Calculations。
从函数式编程角度思考awk
昨天读到这篇文章:Awk, Unix, and functional programming,作者从函数式编程角度考虑awk
,把awk
总结为一个函数式程序:
Awk(action) =
for each file
for each input line
for each pattern
if pattern matches input line
do action(fields)
即把awk
程序看做一个函数,action
作为awk
的参数。对符合pattern
的输入行,调用action
处理这一行的每个field
。上面这段伪代码可以帮助我更好地理解awk
。
你用对awk了吗?
今天折腾OmniOS
上的awk
,结果发现很简单的一个程序居然执行出错:
root@localhost:/root# awk 'function print_name_and_age(name, age) { print name" is "age" old" } {print_name_and_age($1, $2)}'
awk: syntax error near line 1
awk: bailing out near line 1
而相同的程序在gawk
下运行的好好的。求助stackoverflow,得到结论如下:
(1)OmniOS
上有nawk
,/usr/bin/awk
(默认的awk
)和/usr/xpg4/bin/awk
。建议使用nawk
。/usr/bin/awk
是老版本的awk
,很多feature
都不支持(基于illumos
内核的操作系统,包括Solaris
可能都需要注意这个问题)。
(2)“bailing out
”是老版本awk
的输出日志。所以一旦有这样的日志输出,需要考虑一下是不是使用的awk
版本有问题。
awk数组笔记
1.awk
中的数组是一维数组,使用时不用事先声明。第一次使用数组元素时,会自动生成数组元素的值,默认为空字符串""
和数字0
。请参考以下例子:
Nan:~ nanxiao$ awk 'END {if (arr["A"] == "") print "Empty string"}'
Empty string
Nan:~ nanxiao$ awk 'END {if (arr["A"] == 0) print "Number 0"}'
Number 0
2.awk
中的数组是关联数组(associative array
),数组下标为字符串。
3.使用for
循环可遍历数组下标:
其中访问数组下标的顺序与具体的实现相关。此外,如果在遍历时加入了新的元素,那么程序运行结果是不确定的。
4.使用subscript in array
表达式来判断数组是否包含指定的数组下标。如果array[subscript]
存在,表达式返回1
,反正返回0
。
注意:使用subscript in array
不会创建array[subscript]
,而if (array[subscript] != "")
则会创建array[subscript]
(如果array[subscript]
不存在的话)。
5.删除数组元素:delete array[subscript]
。
6.split(string, array, fs)
使用fs
作为字段分隔符(field separator
),把字符串string
拆分后,传到array
数组中。第一个字段保存在array["1"]
,第二个字段保存在array["2"]
…。如果没有指定fs
,则使用内置变量FS
作为分隔符。
7.多维数组。awk
不直接支持多维数组,但可以通过一维数组来模拟。
8.数组元素不能再是数组。
一份很好的关于“正则表达式/sed/awk”的总结
昨天在网上无意中找到Brendan Gregg
大神于2004
年总结的一份关于“正则表达式/sed/awk
”材料,内容不长,但非常实用,可以作为写脚本时一个很好的参考。链接在这里。