awk - 运维三剑客

简介

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


完全体可以分为以下5个部分

image


变量

内置变量

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
posted @   难德糊涂  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示