awk - 运维三剑客
简介
awk 常用于循环读取文本,获取某列,像这样 awk -F":" '{print $1}''
实际上它还可以对获取的值做处理,并输出结果
经常见到用朋友用 awk 做统计,搞一下它的用法做个记录
完全体可以分为以下5个部分

变量
内置变量
awk 有一些内置的变量,经常出现在各个大佬的脚本中
$0: 表示整行$1,$2..:表示某列NR:表示行号NF:列总数$NF:也就是最后一列的值FS:输入列分隔符,默认是" ",也可以通过awk -F指定OFS:输出列分隔符,默认是" "。(output field sep)RS:输入行分隔符,默认是"\n"ORS:输出行分隔符,默认是"\n"。(output row sep)
变量赋值
有了变量之后,就可以进行赋值、计算和拼接
x = 1:赋值,弱类型,赋值时不用在意类型x = "1"x: 拼接字符串x++或x+=1:计算
变量使用的示例
# 根据列打印
awk -F: '{print $1,$6}' /etc/passwd
# 在 BEGIN 块中设置输入分隔符
awk 'BEGIN {FS=":"} {print $1,$6}' /etc/passwd
awk -F: '{print $1"="$6}' /etc/passwd
# 在 BEGIN 块中设置输入及输出分隔符
awk 'BEGIN {FS=":";OFS="="} {print $1,$6}' /etc/passwd
# 设置变量, 计算某一列的和
# 变量的赋值和引用都不需要加$符号
awk -F: 'BEGIN{sum=0} {sum+=$3} END{print sum}' /etc/passwd
# 支持隐式设置, 与上边等价(主要是怕有些大佬按这个写法写,看到了不懂)
awk '{sum+=$5} END{print sum}' a
格式化输出
变量支持字符串类型,就有了格式化输出的概念
%s:字符串占位符,自动长度%10s:设置占用长度为10,右对齐%-10s:设置占用长度为10,左对齐
格式化输出示例
需要使用 printf 函数
# 替换字符串, 默认自动长度
# 这里就是之前提到的,只有 BEGIN 块,可以不指定输入
[root@master ~]# awk 'BEGIN {printf "%s: %s\n", "foo", "bar"}'
foo: bar
# 设置字符串占用长度, 前边左对齐,后边右对齐
[root@master ~]# awk 'BEGIN {printf "|%10s|: |%-10s|\n", "foo", "bar"}'
| foo|: |bar |
# 如果超过限制长度自动扩充
[root@master ~]# awk 'BEGIN {printf "|%3s|: |%-3s|\n", "foooooo", "barrrrr"}'
|foooooo|: |barrrrr|
逻辑
主要用于逐行处理,图中 pattern 的部分
匹配
匹配可以是通配符,也可以是正则
绝对匹配时可以不加 //, 模糊匹配必须加 //
如果是按列匹配也可以使用"",但是不通用,建议用//
绝对匹配(适用于字符串和数字):- 针对列匹配:
awk '($m~root) { print $n }' filename - 整行匹配:
awk '(/root/) { print $n }' filename
- 针对列匹配:
模糊匹配(适用于字符串和数字):awk '($m~/ro.*t/) { print $n }' filename比大小(适用于数字):awk '($m>42) { print $n }' filename
关联符
&&(与):awk '($m>2&&$m<9) { print $n } filename'||(或):awk '($m<2||$m>5) { print $n }' filename!(非):- 针对列不匹配
awk '($m!~/yky/) { print $n } filename - 针对整行不匹配:
awk '(!/root/) { print $n }' filename
- 针对列不匹配
if 判断
awk 通过匹配也可以实现 if 判断的效果
与匹配模式的区别是,if 判断块需要写在 { } 里边,因为每行都要执行判断
等于(适用于字符串和数字):awk '{ if($m=="x") print $n }' filename不等于(适用于字符串和数字):awk '{ if($!="x") print $n }' filename大于/小于/大于等于/小于等于/等于(仅适用于数字):awk '{ if($m<5||9<=$m) print $n }' filename
循环
支持 for 循环和 while 循环
支持 break 和continue
我感觉不是很常用,我没用过= =
for 循环
# 在 BEGIN 中使用 for 循环
awk '
BEGIN {
for(i=0;i<10;i++)
print i
}'
# 这个相当于每读一行文本,都会执行一次完整的for循环
awk '
{
for( i = 1; i < 10; i += 2 )
{print}
}' /etc/passwd
# for range 循环(配合数组使用)
# 两个赋值,一个循环输出
awk '
BEGIN {
arr["a"]="aaa"
arr["b"]="bbb"
for(x in arr)
print arr[x]
}'
while 循环
# 两种写法结果等价
awk '
BEGIN {
while (i < 10) {
print i
i++
}
}'
awk '
BEGIN {
i = 1
do {
print i
i++
} while (i < 10)
}'
引用
引用命令
如果 awk 命令太长,还可以预置成一个文件,在通过 awk -E 的方式引用
文件中只需要声明 awk ' ' 中间的内容
[root@node02 ~]# cat a
BEGIN{
print "----------"
}
[root@node02 ~]# awk -E a
----------
引用变量
这里需要先使用 -v 传入变量
[root@node02 ~]# cat a
BEGIN{
print "sum 初始值为: "sum
}
( $2!=3 ) {sum+=$2}
END{
print sum
}
[root@node02 ~]# cat b
a 1
b 2
c 3
d 4
e 5
# 如果不指定sum变量的初始值,默认为0
[root@node02 ~]# awk -E a b
sum 初始值为:
12
# 但是如果指定的话
[root@node02 ~]# awk -v sum=2 -E a b
sum 初始值为: 2
14
数组
定义数组,循环输出
awk '
BEGIN {
assoc["key1"] = "val1"
assoc["key2"] = "val2"
for (key in assoc)
print assoc[key];
}'
函数
| 函数名 | 示例 | 说明 |
|---|---|---|
| length(str) | awk 'BEGIN {a=length("aaa"); print a}' |
字符串长度 |
| printf("formatStr", ele1, ele2) | awk 'BEGIN {printf("%s: %s\n", "foo", "bar")}' |
格式化字符串 |
| toupper(str) | 转大写 | |
| tolower(str) | 转小写 | |
| index(a, b) | awk '{print index($0,"root")}' /etc/passwd |
字符串a中出现字符串b的索引, 未找到为0 |
欢迎加 1092845214 交流沟通呀~
本文来自博客园,作者:难德糊涂,转载请注明原文链接:https://www.cnblogs.com/yangkaiyue/p/18235896

浙公网安备 33010602011771号