• awk笔记


    快速上手

    内建变量与打印

    • NF(可以理解为Number of fields)
      • 内建变量,表示当前行的字段数量
      • {print NF, $1, $NF}
    • NR(可以理解为Number of rows)
      • 内建变量,表示当目前为止读到的行数。
    • 打印文本
      • 在 print 语句中, 被双引号包围的文本会和字段, 以及运算结果一起输出.
      • {print "total pay for"}
    • printf
      • { printf("total pay for %s is $%.2f\n", $1, $2 * $3) }
      • { printf("%-8s $%6.2f\n", $1, $2 * $3) }
    • 输出排序
      • awk '{ printf("%6.2f %s\n", $2 * $3, $0) }' emp.data | sort -n

    选择

    打印那些报酬超过 50 的
    $2 * $3 > 50 { printf("$%.2f for %s\n", $2 * $3, $1) }

    打印所有第一个字段是Susie 的行:
    $1 == "Susie"

    通过正则表达式, 打印所有包含 Susie 的行
    /Susie/

    模式组合

    模式可以使用括号和逻辑运算符进行组合, 逻辑运算符包括 &&, ||, 和 !。

    打印那些 $2 至少为 4, 或者 $3 至少为 20 的行:

    $2 >= 4 || $3 >= 20
    
    • 1

    两个条件都满足的行只输出一次. 将这个程序与下面这个程序作对比, 它包含两个模式,如果某行对这两个条件都满足, 它会被打印两次:

    $2 >= 4
    $3 >= 20
    
    • 1
    • 2

    打印不满足($2 小于 4, 并且 $3 也小于 20)的行

    !($2 < 4 && $3 < 20)
    
    • 1

    数据验证

    真实的数据总是存在错误. 检查数据是否具有合理的值, 格式是否正确, 这种任务通常称作数据验证 (data
    validation), 在这一方面 awk 是一款非常优秀的工具.
    数据验证在本质上是否定: 不打印具有期望的属性的行, 而是打印可疑行. 接下来的程序使用比较模式, 将
    5 条合理性测试应用到 emp.data 的每一行:

    NF != 3 { print $0, "number of fields is not equal to 3" }
    $2 < 3.35 { print $0, "rate is below minimum wage" }
    $2 > 10 { print $0, "rate exceeds $10 per hour" }
    $3 < 0 { print $0, "negative hours worked" }
    $3 > 60 { print $0, "too many hours worked" }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    如果数据没有错误, 就不会有输出。

    BEGIN 与 END

    特殊的模式 BEGIN 在第一个输入文件的第一行之前被匹配, END 在最后一个输入文件的最后一行被处理
    之后匹配. 这个程序使用 BEGIN 打印一个标题:

    BEGIN { print "NAME RATE HOURS"; print "" }
    { print }
    
    • 1
    • 2

    可以在同一行放置多个语句, 语句之间用分号分开。注意 print "" 打印一个空行, 它与一个单独的 print
    不相同, 后者打印当前行

    计算

    awk可以用来进行简单的数学或字符串计算,而且可以使用内建变量、自定义变量来计算和存储数据。
    awk 中, 用户创建的变量不需要事先声明就可以使用。

    计数

    用一个变量 emp 计算工作时长超过 15 个小时的员工人数:

    $3 > 15 { emp = emp + 1 }
    END { print emp, "employees worked more than 15 hours" }
    
    • 1
    • 2

    总和与平均数

    利用 NR 来计算平均报酬:

    { pay = pay + $2 * $3 }
    END { print NR, "employees"
    	  print "total pay is", pay
    	  print "average pay is", pay / NR
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    很明显, printf 可以用来产生更加美观的输出. 这个程序有一个潜在的错误: 一种不常见的情况是 NR 的值为
    0, 程序会尝试将 0 作除数, 此时 awk 就会产生一条错误消息。

    字符串拼接

    可以通过旧字符串的组合来生成一个新字符串; 这个操作叫作拼接 (concatenation).

    { names = names $1 " " }
    END { print names }
    
    • 1
    • 2

    打印最后一行

    虽然在 END 动作里, NR 的值被保留了下来, 但是 $0 却不会。
    打印文件最后一行

    { last = $0 }
    END { print last }
    
    • 1
    • 2

    内建函数

    awk 也提供用来计算其他值的内建函数. 求平方根, 取对数, 随机数, 除了这些数学函数, 还有其他用来操作文本的函数. 其中之一是 length, 它用来计算字符串中字符的个数.

    计算每一个人的名字的长度:

    { print $1, length($1) }
    
    • 1

    行,单词与字符的计数

    使用 length, NF 与 NR 计算行, 单词与字符的数量, 为方便起见, 我们将每个字段都当成一个单词

    { nc = nc + length($0) + 1
    nw = nw + NF
    }
    END { print NR, "lines,", nw, "words,", nc, "characters" }
    
    • 1
    • 2
    • 3
    • 4

    流程控制语句

    Awk 提供了用于决策的 if-else 语句, 以及循环语句, 所有的这些都来源于 C 语言. 它们只能用在动作(Action) 里。

    if else

    $2 > 6 { n = n + 1; pay = pay + $2 * $3 }
    END { if (n > 0)
    	print n, "employees, total pay is", pay,
    			 "average pay is", pay/n
    else
    	print "no employees are paid more than $6/hour"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    while

    一个 while 含有一个条件判断与一个循环体. 当条件为真时, 循环体执行。

    { i = 1
    	while (i <= $3) {
    		printf("\t%.2f\n", $1 * (1 + $2) ^ i)
    			i = i + 1
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    for

    大多数循环都包括初始化, 测试, 增值, 而 for 语句将这三者压缩成一行。

    { for (i = 1; i <= $3; i = i + 1)
    	  printf("\t%.2f\n", $1 * (1 + $2) ^ i)
    }
    
    • 1
    • 2
    • 3

    数组

    一个简单的例子。
    下面这个程序按行逆序显示输入数据.。第一个动作将输入行放入数组 line 的下一个元素中;
    也就是说, 第一行放入 line[1], 第二行放入 line[2], 依次类推.。
    END 动作用一个 while 循环, 从数组的最后一个元素开始打印, 一直打印到第一个元素为止。

    {line[NR] = $0}
    END { i = NR
    		while(i > 0){
    			print line[i]
    			i = i-1
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    用for循环实现等价程序:

    { line[NR] = $0 } # remember each input line
    END { for (i = NR; i > 0; i = i - 1)
    	print line[i]
    }
    
    • 1
    • 2
    • 3
    • 4

    实用“一行”手册

    虽然 awk 可以写出非常复杂的程序, 但是许多实用的程序并不比我们目前为止看到的复杂多少。
    这里有一些小程序集合, 对读者应该会有一些参考价值. 大多数是我们已经讨论过的程序的变形。

    1. 输入行的总行数
      END { print NR }
    2. 打印第10行
      NR == 10
    3. 打印每一个输入行的最后一个字段
      { print $NF }
    4. 打印最后一行的最后一个字段
      { field = $NF }
      END { print field }
      
      • 1
      • 2
    5. 打印字段数多余4个的输入行
      NF>4
    6. 打印最后一个字段值大于4的输入行
      $NF >4
    7. 打印属于输入行的字段数的总和
      { nf = nf + NF }
      END { print nf }
      
      • 1
      • 2
    8. 打印包含Beth的行的数量
      /Beth/ { nlines = nlines + 1 }
      END { print nlines }
      
      • 1
      • 2
    9. 打印具有最大值的第一个字段,以及包含它的行(假设$1总是正的)
    $1 > max { max = $1; maxline = $0 }
    END { print max, maxline }
    
    • 1
    • 2
    1. 打印至少包含一个字段的行
      NF > 0
    2. 打印长度超过80个字符的行
      length($0) > 80
    3. 在每一行的前面加上它的字段数
      { print NF, $0 }
    4. 打印每一行的第1与第2个字段,但顺序相反
      {print $2, $1}
    5. 交换每一行的第1与第2个字段,并打印该行
      { temp = $1; $1 = $2; $2 = temp; print}
    6. 将每一行的第一个字段用行号代替
      { $1 = NR; print }
    7. 打印删除了第2个字段后的行
      { $2 = ""; print }
    8. 将每一行的字段按逆序打印
      { for(i=NF; i>0; i=i-1)
      	printf("%s ", $i)
        printf("\n")
      }
      
      • 1
      • 2
      • 3
      • 4
    9. 打印每一行的所有字段值之和
      { sum = 0
        for(i=1; i<= NF; i=i+1) sum = sum + $i
        print sum
      }
      
      • 1
      • 2
      • 3
      • 4
    10. 将所有行的所有字段值累加起来
      { for (i = 1; i <= NF; i = i + 1) sum = sum + $i }
      END { print sum }
      
      • 1
      • 2
    11. 将每一行的每一个字段用它的绝对值替换
      { for (i = 1; i <= NF; i = i + 1) if ($i < 0) $i = -$i
      print
      }
      
      • 1
      • 2
      • 3

    系统学习

    • 待办
  • 相关阅读:
    React中的dispatch()
    Qt QPen
    数据挖掘(一)使用 Apriori 算法进行关联分析
    基于RK3568的鸿蒙通行一体机方案项目
    [附源码]计算机毕业设计JAVA电竞选手信息管理系统论文2022
    300分钟吃透分布式缓存-17讲:如何理解、选择并使用Redis的核心数据类型?
    iNFTnews | DAO在NFT领域中的作用
    Scala面向对象部分演示(IDEA开发)
    Ubuntu - 网络
    Euro-NCAP-2023-安全驾驶辅助驾驶员状态监测DMS和限速辅助测试流程-中文版
  • 原文地址:https://blog.csdn.net/qq_51470638/article/details/126016118