一、简介
-
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
-
首先,调用 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。
关系运算符 | 描述 | 示例 |
---|---|---|
< | 小于 | $1 < $2 |
> | 大于 | $1 > $2 |
<= | 小于等于 | $1 <= $2 |
>= | 大于等于 | $1 >= $2 |
== | 等于 | $1 == $2 |
!= | 不等于 | $1 != $2 |
示例:
-
><
可以作为字符串比较,也可以用作数值比较,关键看操作数,如果是字符串就会转换为字符串比较。两个都为数字,才转为数值比较。 - 字符串比较:按照ASCII码顺序比较。
逻辑运算符 | 描述 | 示例 |
---|---|---|
&& |
逻辑与 | $1 > 10 && $2 < 5 |
|| |
逻辑或 | $1 > 10 || $2 < 5 |
! |
逻辑非 | !($1 > 10) |
示例:
字符串运算符 | 描述 | 示例 |
---|---|---|
~ | 匹配正则表达式 | $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) |
示例:
赋值运算符 | 描述 | 示例 |
---|---|---|
= | 简单赋值 | x = 1 |
+= | 加法赋值 | x += 1 |
-= | 减法赋值 | x -= 1 |
*= | 乘法赋值 | x *= 2 |
/= | 除法赋值 | x /= 2 |
%= | 求余赋值 | x %= 3 |
**= | 幂运算赋值 | x **= 2 |
示例:
a+5;等价于:a=a+5;其他同类
1.2.2 三目运算符
- 根据条件来选择两个不同值中的一个,语法:
条件 ? 值1 : 值2
- 条件:一个返回布尔值(真或假)的表达式。
-
?
:如果条件为真,则执行接下来的操作。 -
值1
:如果条件为真,则返回此值。 -
:
:分隔两个可能的值。 -
值2
:如果条件为假,则返回此值。
示例1:
示例2:
awk '{ if ($1 > 25) print "大于25"; else print "小于或等于25"}' data.txt
简化版本:
awk '{ print ($1 >25) ? "大于25" : "小于等于25" }' data.txt
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}
案例:
- 单行转多行:
echo 1:2:3 |awk 'BEGIN{RS=":"}{print $0}'
- 多行转一行(1)
echo '1
2
3' | awk 'BEGIN{RS="";FS="\n";OFS=":"}{$1=$1;print $0}'
- 多行转一行(2)
echo '1
2
3' | awk 'BEGIN{ORS=":"}{$1=$1;print $0}'
- 计算平均值
` 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的词典类型
- 统计多加机构的营业额
- 统计多加机构的营业额平均值