linux工具-awk

1. 基本知识

1.1. 名称由来

awk是其设计者名字首字母.

1.2. 语法格式

awk [options] 'pattern {action}' filename

1.3. 执行流程

对如下语句:

awk 'BEGIN {action1} pattern {action2} END {action3}' filename

执行流程如下:

  1. 执行BEGIN {action1}语种块中的语句.
  2. 从文件或STDIN逐行读取, 对每一行执行pattern {action2}, 直到全部读取完成.
  3. 执行END {action3}语种块中的语句.

例子: 打印每一行, 并且在开头和结尾分别打印Start和END.print语句不带参数时就打印整行内容

例子:对第2列进行累加, 在BEGIN中为i赋初值, 在END中打印i(累加结果).

$ echo -e "a 1 a
a 2 a
a 3 a" |   
> awk 'BEGIN {i=0} {i+=$2} END {print i}'  
6  

1.4. 术语解释

术语 说明
记录 awk把每一个以换行符结束的行称为一个记录, NR即记录的个数
记录中每个单词称做"域", 默认以空格或Tab分隔, NF即域的个数.

2. options

选项 说明
-v 参数传递
-f 指定脚本文件
-F 指定分隔符
-V 查看awk版本号

例子1:指定列分隔符

文件内容

$ cat demo.txt  
root:x:0:0:root:/root:/bin/bash  
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin  
bin:x:2:2:bin:/bin:/usr/sbin/nologin  
sys:x:3:3:sys:/dev:/usr/sbin/nologin  
sync:x:4:65534:sync:/bin:/bin/sync  

通过-F指定列分隔符

$ # -F和:之间没有空格  
$ awk -F: '{printf "%-6s %-9s %s
", $1, $6, $7}' demo.txt  
root   /root     /bin/bash  
daemon /usr/sbin /usr/sbin/nologin  
bin    /bin      /usr/sbin/nologin  
sys    /dev      /usr/sbin/nologin  
sync   /bin      /bin/sync  
$   
$ # -F和:之间有空格, 这时分隔符最好放到引号中, 否则使用#等分隔时会报错.  
$ awk -F ':' '{printf "%-6s %-9s %s
", $1, $6, $7}' demo.txt  
root   /root     /bin/bash  
daemon /usr/sbin /usr/sbin/nologin  
bin    /bin      /usr/sbin/nologin  
sys    /dev      /usr/sbin/nologin  
sync   /bin      /bin/sync  

通过-v FS指定列分隔符

$ awk -v FS=: '{printf "%-6s %-9s %s
", $1, $6, $7}' demo.txt  
root   /root     /bin/bash  
daemon /usr/sbin /usr/sbin/nologin  
bin    /bin      /usr/sbin/nologin  
sys    /dev      /usr/sbin/nologin  
sync   /bin      /bin/sync  

3. pattern {action}

awk_script由pattern和Action组成,
例如:

awk 'BEGIN {action1} pattern {action2} END {action3}' filename

模式:有4种模式

  1. /正则表达式/
  2. 关系表达式:使用运算符进行操作, 比如字符串、数字的比较测试.
  3. 模式匹配表达式:用运算符:~和~!, 分别表示匹配、不匹配.
  4. BEGIN/END语句块、pattern语句块.

action:由一个或多个命令/函数/表达式组成, 它们之间用换行符或分号隔开.
action主要有以下类型:

  1. 变量或数组赋值
  2. 输出命令
  3. 内置函数
  4. 控制流语句

注意:

  1. BEGIN {action1}, 只在开始执行一次, 是可选的, 默认无BEGINaction.
  2. pattern {action2}, 对匹配pattern的行进行操作, pattern是可选的, 默认对每一行进行action2, {action2}也是可选的, 默认打印匹配pattern的行, 但是pattern和{action2}必须出现一个, 不能都省略.
  3. END {action3}, 只在结尾执行一次, 是可选的, 默认无END action.

例子1:
输入文件内容:

$ cat a.txt  
line first    1  
line second   2  
line third    3  
line forth    4  
line fifth    5  
line sixth    6  
line seventh  7  

使用BEGIN、END等

$ # 在BEGIN的action中, 先打印一行内容, 再给i赋初值  
$ # 在遍历line的语句中, 打印第2、3列, 并对第3列累加  
$ # 在END的action中, 打印第3列的累加结果  
$ awk 'BEGIN {print "C2", "C3"; i=0} {print $2, $3; i+=$3} END {print "total=",i}' a.txt  
C2 C3  
first 1  
second 2  
third 3  
forth 4  
fifth 5  
sixth 6  
seventh 7  
total= 28  

注意:

  1. 在print语句中,
    字符串要写在双引号里,
    字符串之间用逗号分隔,
    变量可以直接赋初值,
    变量使用时不能带双引号
  2. 变量赋值和使用时不需要带$号($1/$2等不受此限制)
  3. 多个action语句之间使用分号分隔.

4. 运算符

运算符 说明
赋值运算符 --------
= 赋值语句
逻辑运算符 --------
|| 逻辑或
&& 逻辑与
正则运算符 --------
~ 正则匹配
~! 正则不匹配
关系运算符 --------
<, <= 小于, 小于等于
>, >= 大于, 大于等于
== 等于
!= 不等于
算术运算符 --------
+, - 加, 减
*, /, % 乘, 除, 取余
+, -, ! 一元加/减/非
^, ***
++, -- 自增, 自减
其它运算符 --------
$ 字段引用
空格 字符串连接
?: 三元运算
in 元素是否存在于数组

例: 只处理奇数行并输出

$ awk -F: 'NR%2==1 {printf "%s) %-6s %-9s %s
", NR, $1, $(NF-1), $NF}' demo.txt  
1) root   /root     /bin/bash  
3) bin    /bin      /usr/sbin/nologin  
5) sync   /bin      /bin/sync  

例: 只处理$1等于root或bin的行, 使用||

$ awk -F: '$1=="root"||$1=="bin" {printf "%s) %-6s %-9s %s
", NR, $1, $(NF-1), $NF}' demo.txt  
1) root   /root     /bin/bash  
3) bin    /bin      /usr/sbin/nologin  

5. 内置变量

内置变量 说明
命令行 --------
ARGC 命令行参数个数
ARGV 命令行参数数组
文件名 --------
FILENAME 当前文件名
计数 --------
FNR 各文件分别计数的行号
NF 当前行的字段个数(当前行分成了几列)
NR 行号
分隔符 --------
FS 输入字段分隔符, 默认为空白字符
OFS 输出字段分隔符, 默认为空白字符
RS 输入记录分隔符(输入换行符)
ORS 输出记录分隔符(输出换行符)
记录 --------
$0 完整的输入记录
$n 当前记录的第n个字段, 字段间由FS分隔

例: 使用NF, NF表示字段数, 本例中NF=7, $NF即$7表示最后一个字段, $(NF-1)表示倒数第二字段

$ awk -F: '{printf "%-6s %-9s %s
", $1, $(NF-1), $NF}' demo.txt  
root   /root     /bin/bash  
daemon /usr/sbin /usr/sbin/nologin  
bin    /bin      /usr/sbin/nologin  
sys    /dev      /usr/sbin/nologin  
sync   /bin      /bin/sync  

例: 使用NR, NR表示当前行的行号

$ awk -v FS=: '{printf "%s) %-6s %-9s %s
", NR, $1, $(NF-1), $NF}' demo.txt  
1) root   /root     /bin/bash  
2) daemon /usr/sbin /usr/sbin/nologin  
3) bin    /bin      /usr/sbin/nologin  
4) sys    /dev      /usr/sbin/nologin  
5) sync   /bin      /bin/sync  

6. 变量

awk中, 变量不需要定义就可以直接使用, 变量类型可以是数字或字符串.

例:如果第一个域匹配test, 则把第二第三个域相加并打印.

awk '$1 ~ /test/ {count=$2+$3; print count}' filename

域变量可以修改:
例: 如果第一个域等于"root", 则把它赋值为test并打印.

awk '$1=="root" {$1="test"; print}' filename

7. 条件语句

if语句

如果第三个域大于3, 则打印一个第二第三域和一个"match"字符, 各字符之间可以有空格, 也可以没有, 字符串要写到双引号中.

awk '{if ($3>3) print $2 "	" $3 "	" "match"}' a.txt

if-else if-else语句
有多个分支, 各分支的语句要写在大括号中.

awk '{if ($3<=2) {print "0~2"} else if ($3<=4) {print "3~4"} else {print "5~n"}}' a.txt

8. 循环语句

  1. awk有三种循环:while、for、special for
  2. 可以使用break和continue.
  3. next语句从输入文件中读取一行, 然后从头开始执行awk脚本.
  4. exit语句用于结构awk程序, 但不会略过END块.

例子:

awk '{i=1; while(i<=NF){print i, $i; i++}; print "------"}' a.txt

说明:

  1. NF是当前行(记录)的字段(域)数量, $i是第i个字段(从1开始).
  2. 注意:print语句中, i和$i是不同的东西, i是循环变量, $i是第i个字段.
  3. 本例以字段数为循环条件, 遍历每个字段并打印.

例子:

awk '{for (i=1;i<=NF;i++) {print i, $i}; print "------"}' a.txt

说明:作用同上, 将while语句改为for语句实现.

special for用来遍历关联数组.见关联数组.for(i in name) {print i, name[i]}

9. 数组

在awk中数据的下标可以是数字, 也可以是字母(称为关联数组, 类似于python中的字典).

例子:

awk '{name[i++]=$2} END {for (i=0;i<NR;i++) {print i, name[i]}}' a.txt

说明:

  1. 将每行的第二字段存入数组, 在结尾遍历数组并打印.
  2. name是一个数组, 不用声明, 直接赋值.
  3. 给数组赋值时, 直接对下标赋值, 不需要管该下标是否存在.
  4. 数组下标变量i自动初始化为0, 然后每处理一个记录自动加1.
  5. NR是当前行的行号(从1开始), 在END块中NR自动变成总行数, 用来遍历数组.

例子:

awk '/s/ {name[NR]=$2} END {for(i in name) {print i, name[i]}}' a.txt

说明:

  1. 如果某行匹配/s/, 则给数组赋值, 下标是行号, 值是$2, 在结尾遍历数组.
  2. name的下标虽然是数字, 但可以是不连续的.

10. 内置函数

https://www.gnu.org/software/gawk/manual/html_node/Built_002din.html#Built_002din

函数 作用
toupper() 字符串转为大写
tolower() 字符串转为小写
length() 返回字符串长度
substr() 返回子字符串
sin() 正弦
cos() 余弦
sqrt() 平方根
rand() 随机数

例: 使用toupper()将第一字段转为大写

$ awk -F: '{printf "%s) %-6s %-9s %s
", NR, toupper($1), $(NF-1), $NF}' demo.txt  
1) ROOT   /root     /bin/bash  
2) DAEMON /usr/sbin /usr/sbin/nologin  
3) BIN    /bin      /usr/sbin/nologin  
4) SYS    /dev      /usr/sbin/nologin  
5) SYNC   /bin      /bin/sync  
原文地址:https://www.cnblogs.com/gaiqingfeng/p/13645984.html