Linux三剑客-awk

image

一、简介

  • awk适合文本处理和报表生成,其语法较为常见,借鉴了某些语言的一些精华,比如C语言等。

  • 在Linux系统日常处理工作中,发挥很重要的作用,掌握了awk将会使工作变得高大上。

  • awk是三剑客的老大,利剑出鞘,必会不同凡响。

  • 语法:awk 'pattern{action}'

二、awk的原理

通过一个简短的命令,了解其工作原理。

awk '{print $0}' /etc/passwd 
echo hhh|awk '{print  "hello, Linux"}' 
awk '{ print "hello,awk" }' /etc/passwd

image
image
image

  • 首先,调用 awk时,我们指定/etc/passwd 作为输入文件。执行 awk 时,它依次对/etc/passwd 中的每一行执行 print 命令。所有输出都发送到 stdout,所得到的结果与执行 cat /etc/passwd 完全相同。

  • 然后,解释{ print }代码块。在 awk 中,花括号用于将几块代码组合到一起,这一点类似于 C 语言。在代码块中只有一条 print 命令。在 awk 中,如果只出现 print 命令,那么将打印当前行的全部内容。

  • 再次说明,awk 对输入文件中的每一行都执行这个脚本。

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

awk -F ":" '{print $1 $3 }' /etc/passwd

awk -F ":" '{print $1 " " $3 }' /etc/passwd

三、语法

1.1 BEGIN和END模块

  • 通常,对于每个输入行,awk都会执行每个代码块一次。

  • 然而,在许多编程情况中,可能需要awk开始处理输入文件之前执行初始化代码。

  • 对于这种情况,awk允许定义一个BEGIN模块。awk在开始处理输入文件之前会执行BEGIN块,因此它是初始化FS(字段分隔符)变量、打印页眉或初始化其他在程序中以后会引用的全局变量的极佳位置。

  • awk还提供END块,在处理了输入文件中的所有行之后执行这个块。通常,END块用于执行最终计算,或打印应该出现在输出流结尾的摘要信息。

1.2 运算符

1.2.1 常用运算符

算数运算符 描述 示例
+ 加法 $1 + $2
- 减法 $1 - $2
* 乘法 $1 * $2
/ 除法 $1 / $2
% 求余 $1 % $2
** 幂运算 $1 ** 2$ (计算$1$的平方)
++ 自增 ++$1 (前缀自增) 或 $1++ (后缀自增)
自减 –$1 (前缀自减) 或 $1-- (后缀自减)

示例:

  • 所有用作算术运算符进行的值,自动转为数值,所有非数值都变为0。
    image
关系运算符 描述 示例
< 小于 $1 < $2
> 大于 $1 > $2
<= 小于等于 $1 <= $2
>= 大于等于 $1 >= $2
== 等于 $1 == $2
!= 不等于 $1 != $2

示例:

  • ><可以作为字符串比较,也可以用作数值比较,关键看操作数,如果是字符串就会转换为字符串比较。两个都为数字,才转为数值比较。
  • 字符串比较:按照ASCII码顺序比较。

image

逻辑运算符 描述 示例
&& 逻辑与 $1 > 10 && $2 < 5
|| 逻辑或 $1 > 10 || $2 < 5
! 逻辑非 !($1 > 10)

示例:
image

字符串运算符 描述 示例
~ 匹配正则表达式 $1 ~ /abc/
!~ 不匹配正则表达式 $1 !~ /abc/
length() 返回字符串长度 length($1)
index() 返回子字符串的起始位置 index($1, abc)
substr() 返回子字符串 substr($1, 3, 5)
split() 分割字符串 split(“a b c”, a, " ")
gensub() 替换字符串 gensub(/abc/, “xyz”, “g”, $1)
tolower() 转换为小写 tolower($1)
toupper() 转换为大写 toupper($1)

示例:
image

赋值运算符 描述 示例
= 简单赋值 x = 1
+= 加法赋值 x += 1
-= 减法赋值 x -= 1
*= 乘法赋值 x *= 2
/= 除法赋值 x /= 2
%= 求余赋值 x %= 3
**= 幂运算赋值 x **= 2

示例:
a+5;等价于:a=a+5;其他同类
image

1.2.2 三目运算符

  • 根据条件来选择两个不同值中的一个,语法:条件 ? 值1 : 值2
    • 条件:一个返回布尔值(真或假)的表达式。
    • ?:如果条件为真,则执行接下来的操作。
    • 值1:如果条件为真,则返回此值。
    • ::分隔两个可能的值。
    • 值2:如果条件为假,则返回此值。

示例1:
image

示例2:
awk '{ if ($1 > 25) print "大于25"; else print "小于或等于25"}' data.txt

简化版本:
awk '{ print ($1 >25) ? "大于25" : "小于等于25" }' data.txt
image

1.2.3 常用 awk 内置变量

变量名 属性
$0 当前记录
$1 当前记录的第1个字段
$n 当前记录的第n个字段
$NF 当前记录中的字段个数,就是有多少列
$(NF-1) 倒数第二个字段
FS 输入字段分隔符,默认是空格
RS 输入记录分隔符,默认为换行符
NR 已经读出的记录数,就是行号,从1开始
OFS 输出字段分隔符,默认也是空格
ORS 输出的记录分隔符,默认为换行符
  • FS=“\t”:一个或多个Tab分隔。

1.2.4 pattern表达式

  • 正则匹配:$1 ~/pattern/ /pattern/
  • 比较表达式:$2>2$1=="b"

1.2.5 awk pattern 匹配表达式案例

  • 开始和结束:awk 'BEGIN{}END{}'

  • 正则匹配:

    • 整行匹配:awk '/Running/'
    • 字段匹配:awk '$2~/xxx/'
  • 行数表达式:

    • 取第二行:awk 'NR==2'
    • 去掉第一行:awk 'NR>1'
  • 区间选择:

    • awk '/aa/,/bb/
    • awk '/1/,NR==2'

1.2.6 action行为表达式{action}

  • 打印:{print $0}{print $2}
  • 赋值:$1="abc"
  • 处理函数
  • 原始内容
  • 更新后内容{$1=$1;print $0}

案例:

  1. 单行转多行:echo 1:2:3 |awk 'BEGIN{RS=":"}{print $0}'

  1. 多行转一行(1)
echo '1
2
3' | awk 'BEGIN{RS="";FS="\n";OFS=":"}{$1=$1;print $0}'

image

  1. 多行转一行(2)
echo '1
2
3' | awk 'BEGIN{ORS=":"}{$1=$1;print $0}'

image

  1. 计算平均值
    ` echo '1,10

2,20
3,30’ | awk ‘BEGIN{total=0;FS=“,”}{total+=$2}END{print total/NR}’`

1.2.7 awk的词典结构array

  • array是稀疏矩阵,类似Python的词典类型
  • 统计多加机构的营业额
  • 统计多加机构的营业额平均值

image