最近在写测试脚本的需求时深感自己Linux命令知识的单薄,有很多常见且强大的命令不会使用,抓紧学习,在这记录一下awk命令解析。

谈到awk自然还会提到grepsed,他们都是Linux下常用的文本处理工具,grep1主要使用正则做文本搜索,并把匹配内容打印出来,而替换匹配内容功能可以由sed2完成。而最早awk3目的是文本处理,基础是“只要在输入数据中有模式匹配,就执行一系列指令”,这听着挺编译原理语义分析的。AWK还具有完全属于其本身的语法,可以支持循环,数组这样复杂的程序设计,比较擅长处理格式化的文本,比如 日志、csv 格式数据。

AWK程序结构

AWK程序是由一系列模式--动作对组成的,写做

1
2
pattern { action }
# 数据中查找的内容 { 找到时执行一系列命令 }

输入按行被分成了一些记录。程序根据pattern匹配每条记录,若成功则执行对应action。

pattern和action都可以省略不写。无pattern默认匹配全部的记录;而无action则是打印原始记录。

简单的AWK表达式之外,pattern可以是BEGIN或END;这两种条件对应的action相当于预处理和收尾。同时,如pattern1, pattern2的条件表示条件pattern1和pattern2的闭区间。

1
awk [-F  field-separator] 'BDGIN{cmds} pattern{cmds} END{cmds}' {filename}

以下约定:记录 (Record) 就是行,字段 (Field) 就是列,BEGIN 是预处理阶段,action 是 awk 真正工作的阶段,END 是最后处理阶段。

$0 指整条记录, $1 指第一个字段,以此类推。

AWK命令

简单打印如:

1
awk '{print $1,$4}' file.txt

格式化打印如:

1
awk '{printf "%-4s %-6s\n",$1,$4}' file.txt

实例如显示/etc/passwd的账户:

1
cat /etc/passwd |awk  -F ':'  '{print $1}' 

Advanced

  1. 可以在pattern中用比较运算符做过滤
  2. 内置变量:
    1. NR:Number of Records已输入记录的条数。
    2. NF:Number of Fields 当前记录中域的个数。记录中最后一个域可以以$NF的方式引用。
    3. FILENAME:当前输入文件的文件名。
    4. FS:“Field Separator域分隔符”,用于将输入记录分割成域。其默认值为“空白字符”,即空格和制表符。FS可以替换为其它字符,从而改变域分隔符。
    5. RS:当前的“记录分隔符”。默认状态下,输入的每行都被作为一个记录,因此默认记录分隔符是换行符。
    6. OFS:“输出域分隔符”,即分隔print命令的参数的符号。其默认值为空格。
    7. ORS:“输出记录分隔符”,即每个print命令之间的符号。其默认值为换行符。OFMT:“输出数字格式”(Format for numeric output),其默认值为"%.6g"。
  3. 变量定义,使用[A-Za-z0-9_]的字符串
  4. 函数定义,与C类似,以关键字function开头,后面跟函数名称,参数列表和函数体。

这里只是对awk命令做了一些基本的介绍,更多复杂的指令还需在实践中加强。

相似博客

linux awk命令详解


题外话:学习压力,缺失反馈等等原因,很久没有更博了,有一些草稿也还未发出来,努力把awk学习一下,发作博客。


  1. grep名称来源于g/re/p(global search regular expression(RE) and print out the line,全局搜索正则表达式并把行打印出来) ↩︎

  2. sed名称来源于s/ed(stream editor,流编辑器) ↩︎

  3. awk名称来源于三个发明人首字母 ↩︎