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.数组元素不能再是数组。