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语句不带参数时就打印整行内容. $0代表整行内容.

awk{printf “Start.%s.End”, $0}’ file.txt

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

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

1.4. 术语解释

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

2. awk的选项: 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\n", $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\n", $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指定列分隔符(FS是内置变量, 表示输入字段的列分隔符)

$ awk -v FS=: '{printf "%-6s %-9s %s\n", $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(动作)组成.

关键词中文名称作用
pattern模式用来选取待处理的行, 可以为空, 表示处理每一行.
action动作对行做什么操作.

例如:

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

3.1 模式pattern

有4种模式, 用来选取待处理的行, 可以为空, 表示处理每一行.

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

3.2 动作action

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

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

注意:

序号语句说明
1BEGIN {action1}只在开始执行一次, 是可选的, 默认无BEGIN action.
2pattern {action2}对匹配pattern的行进行操作, pattern是可选的, 默认对每一行进行action2, {action2}也是可选的, 默认打印匹配pattern的行, 但是pattern和{action2}必须出现一个, 不能都省略.
3END {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元素是否存在于数组中

例: 只处理奇数行并输出

# 说明: NR是行号, $1是第一列内容, NF是当前行列数, $(NF-1)是倒数第二列内容, $NF是最后一列内容
$ awk -F: 'NR%2==1 {printf "%s) %-6s %-9s %s\n", 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\n", 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个字段(从1开始), 字段间由FS分隔

例: 使用NF

# NF表示字段数, 本例中NF=7, 
#    $NF即$7, 表示最后一个字段, 
#    $(NF-1), 表示倒数第二字段
$ awk -F: '{printf "%-6s %-9s %s\n", $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\n", 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 "\t" $3 "\t" "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\n", 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  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值