shell 编程(九):shell 常用工具之 awk


shell 常用工具:awk

sed 主要以为单位来对文件进行处理,而需要对文件按照来进行处理的话就得需要使用 awk 命令。

awk 命令比 sed 命令强的地方在于不仅能以行为单位还能以列为单位来对文件进行处理。

awk 缺省的行分隔符是换行,缺省的列分隔符是连续的空格和 Tab,但是具体的行分隔符和列分隔符都支持自定义。

awk实际上是一门很复杂的脚本语言,还有像 C 语言一样的分支和循环结构,但是基本用法和 sed 类似,awk 命令的基本形式为:

awk option 'script' file1 file2 ...
awk option -f scriptfile file1 file2

和 sed 类似,awk处理的文件既可以由标准输入重定向得到,也可以当命令行参数传入,编辑命令可以直接当命令行参数传入,也可以用 -f 参数指定一个脚本文件,编辑命令的格式为:

/pattern/{actions}
condition{actions}

和 sed 类似,pattern 是正则表达式,actions 是一系列的操作。awk 程序一行一行读出待处理文件,如果某一行与 pattern 匹配,或者满足 condition 条件,则执行相应的 actions,如果一条 awk 命令只有 actions 部分,则 actions 用于待处理文件的每一行。

比如一个 testfile 文件中的内容如下所示:

ProductA  30
ProductB  76
ProductC  55

则如下的命令可以打印出该文件中每一行中的第二列中的内容:

$ awk '{print $2;}' testfile

其中:

  • $0表示当前整个行
  • $1表示第一列
  • $2表示第二列

依次类推。

同时,awk也支持按照某种条件来执行相应的操作。比如,下面的脚本便将 testfile 中产品库存低于75的在行末标注需要订货:

$ awk '$2<75 {printf "%s\t%s\n", $0, "REORDER";} $2>=75 {print $0;} testfile'

可以看到 awk 也有和 c 语言非常相似的 print 函数。

awk 命令的 condition 部分还可以是两个特殊的 condition BEGIN 和 END,对于每个待处理文件,BEGIN后面的 actions 在处理整个文件之前就已经执行了一次,而 END 后面的 actions 在整个文件处理完毕之后还需要在执行一次。

并且 awk 还可以像 C 语言一样来使用变量,但是并不需要定义变量。比如如下的命令来统计一个文件中所有的空行的行数:

$ awk '/^ *$/ {x=x+1;} END {print x;}' testfile

其中,x不需要进行定义,直接使用,初始值为0

awk 中也有一些预先已经定义好的变量,这些变量都具有相应的特殊含义:

  • FILENAME 当前输入文件的文件名,该变量是只读的
  • NR 当前行的行号,该变量是只读的,R代表record
  • NF 当前行所拥有的列数,该变量是只读的,F代表field
  • OFS 输出格式的列分隔符,缺省是空格
  • FS 输入文件的列分融符,缺省是连续的空格和Tab
  • ORS 输出格式的行分隔符,缺省是换行符
  • RS 输入文件的行分隔符,缺省是换行符

比如 /etc/passwd 文件的每一行有若干个字段,字段之间以 : 分隔,就可以重新定义 awk 的列分隔符为 : 并以列为单位处理这个文件。比如,如下的命令便可以打印 /etc/passwd 中的用户账号列表:

$ awk 'BEGIN {FS=":"} {print $1;}' /etc/passwd