分隔符

  • -F fs
    指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。

    1. # 以逗号分割每行,打印第一列,第二列
    2. awk -F, '{print $1,$2}' log.txt
    3. # 使用内建变量,仍然是以逗号分割,打印第一列,第二列
    4. awk 'BEGIN{FS=","} {print $1,$2}' log.txt
    5. # 使用多个分隔符.先使用空格分割,然后对分割结果再使用","分割
    6. awk -F '[ ,]' '{print $1,$2,$5}' log.txt

    赋值变量的方法

  • -v var=value
    赋值一个用户定义变量。

log.txt文本内容如下

  1. 2 this is a test
  2. 3 Are you like awk
  3. This's a test
  4. 10 There are orange,apple,mongo
  1. $ awk -va=1 '{print $1,$1+a}' log.txt #命令
  2. ---------------------------------------
  3. #输出
  4. 2 3
  5. 3 4
  6. This's 1
  7. 10 11
  1. $ awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt #命令
  2. ---------------------------------------------
  3. #输出
  4. 2 3 2s
  5. 3 4 3s
  6. This's 1 This'ss
  7. 10 11 10s

AWK脚本调用

  1. $ awk -f cal.awk log.txt

关于 awk 脚本,我们需要注意两个关键词 BEGIN 和 END。

  • BEGIN{ 这里面放的是**执行前的语句** }
  • END {这里面放的是处理完所有的行后要**执行的语句** }
  • {这里面放的是处理**每一行时要执行的语句**}

DEMO:
文本:score.txt

  1. $ cat score.txt
  2. Marry 2143 78 84 77
  3. Jack 2321 66 78 45
  4. Tom 2122 48 77 71
  5. Mike 2537 87 97 95
  6. Bob 2415 40 57 62

脚本:cal.awk

  1. $ cat cal.awk
  2. #!/bin/awk -f
  3. #运行前
  4. BEGIN {
  5. math = 0
  6. english = 0
  7. computer = 0
  8. printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
  9. printf "---------------------------------------------\n"
  10. }
  11. #运行中
  12. {
  13. math+=$3
  14. english+=$4
  15. computer+=$5
  16. printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
  17. }
  18. #运行后
  19. END {
  20. printf "---------------------------------------------\n"
  21. printf " TOTAL:%10d %8d %8d \n", math, english, computer
  22. printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
  23. }

结果

  1. $ awk -f cal.awk score.txt
  2. NAME NO. MATH ENGLISH COMPUTER TOTAL
  3. ---------------------------------------------
  4. Marry 2143 78 84 77 239
  5. Jack 2321 66 78 45 189
  6. Tom 2122 48 77 71 196
  7. Mike 2537 87 97 95 279
  8. Bob 2415 40 57 62 159
  9. ---------------------------------------------
  10. TOTAL: 319 393 350
  11. AVERAGE: 63.80 78.60 70.00

常见函数

基本函数

参考:https://www.runoob.com/w3cnote/awk-built-in-functions.html

自定义函数

  1. # 返回最小值
  2. function find_min(num1, num2)
  3. {
  4. if (num1 < num2)
  5. return num1
  6. return num2
  7. }
  8. # 返回最大值
  9. function find_max(num1, num2)
  10. {
  11. if (num1 > num2)
  12. return num1
  13. return num2
  14. }
  15. # 主函数
  16. function main(num1, num2)
  17. {
  18. # 查找最小值
  19. result = find_min(10, 20)
  20. print "Minimum =", result
  21. # 查找最大值
  22. result = find_max(10, 20)
  23. print "Maximum =", result
  24. }
  25. # 脚本从这里开始执行
  26. BEGIN {
  27. main(10, 20)
  28. }
  1. $ awk -f functions.awk
  2. Minimum = 10
  3. Maximum = 20

流程控制

IF

  1. awk 'BEGIN {num = 10; if (num % 2 == 0) printf "%d 是偶数\n", num }'

IF-ELSE

  1. awk 'BEGIN {
  2. num = 11;
  3. if (num % 2 == 0) printf "%d 是偶数\n", num;
  4. else printf "%d 是奇数\n", num
  5. }'

IF-ELSE-IF

  1. awk 'BEGIN {
  2. a=30;
  3. if (a==10)
  4. print "a = 10";
  5. else if (a == 20)
  6. print "a = 20";
  7. else if (a == 30)
  8. print "a = 30";
  9. }'

FOR

  1. awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'

BREAK

  1. awk 'BEGIN {
  2. sum = 0; for (i = 0; i < 20; ++i) {
  3. sum += i; if (sum > 50) break; else print "Sum =", sum
  4. }
  5. }'

Continue

  1. $ awk 'BEGIN {for (i = 1; i <= 20; ++i) {if (i % 2 == 0) print i ; else continue} }'

Exit

  1. awk 'BEGIN {
  2. sum = 0; for (i = 0; i < 20; ++i) {
  3. sum += i; if (sum > 50) exit(10); else print "Sum =", sum
  4. }
  5. }'
  6. echo $?
  7. 10

正则匹配

  1. # 输出第二列包含 "th",并打印第二列与第四列
  2. $ awk '$2 ~ /th/ {print $2,$4}' log.txt
  3. ---------------------------------------------
  4. this a
  5. # 输出包含 "re" 的行
  6. $ awk '/re/ ' log.txt
  7. ---------------------------------------------
  8. 3 Are you like awk
  9. 10 There are orange,apple,mongo
  10. # 忽略大小写
  11. $ awk 'BEGIN{IGNORECASE=1} /this/' log.txt
  12. ---------------------------------------------
  13. 2 this is a test
  14. This's a test
  1. #取反
  2. $ awk '$2 !~ /th/ {print $2,$4}' log.txt
  3. ---------------------------------------------
  4. Are like
  5. a
  6. There orange,apple,mongo
  7. #取反
  8. $ awk '!/th/ {print $2,$4}' log.txt
  9. ---------------------------------------------
  10. Are like
  11. a
  12. There orange,apple,mongo

内建变量

FS:Field Separator 分隔符

  • FS 可以是任意字符或者正则表达式
  • FS 可以多次改变, 不过会保持不变直到被明确修改。不过如果想要改变字段分隔符, 最好是在读入文本之前就改变 FS, 这样改变才会在你读入的文本生效。

OFS: 输出字段分隔符变量

  1. awk -F':' 'BEGIN{OFS="=";} {print $3,$4;}' /etc/passwd

RS:Record Separator 记录分隔符
ORS: 输出记录分隔符变量

  1. $ cat student.txt
  2. Jones
  3. 2143
  4. 78
  5. 84
  6. 77
  7. Gondrol
  8. 2321
  9. 56
  10. 58
  11. 45
  12. RinRao
  13. 2122
  14. 38
  15. 37
  16. 65
  17. Edwin
  18. 2537
  19. 78
  20. 67
  21. 45
  22. Dayan
  23. 2415
  24. 30
  25. 47
  26. 20
  1. # 两个回车作为一个记录的分隔符,单个回车作为记录的内部分隔符
  2. $ cat student.awk
  3. BEGIN {
  4. RS="\n\n";
  5. FS="\n";
  6. }
  7. {
  8. print $1,$2;
  9. }
  10. $ awk -f student.awk student.txt
  11. Jones 2143
  12. Gondrol 2321
  13. RinRao 2122
  14. Edwin 2537
  15. Dayan 2415

NR: 记录数变量
NR(Number of Record) 表示的是已经处理过的总记录数目,或者说行号(不一定是一个文件,可能是多个)。下面的例子,NR 表示行号,在 END 部分,NR 就是文件中的所有记录数目。
NF:一条记录的记录数目
NF(Number for Field)表示的是,一条记录的字段的数目. 它在判断某条记录是否所有字段都存在时非常有用。

  1. cat student-marks
  2. Jones 2143 78 84 77
  3. Gondrol 2321 56 58 45
  4. RinRao 2122 38 37
  5. Edwin 2537 78 67 45
  6. Dayan 2415 30 47
  1. $ awk '{print NR,"->",NF}' student-marks
  2. 1 -> 5
  3. 2 -> 5
  4. 3 -> 4
  5. 4 -> 5
  6. 5 -> 4

FILENAME: 当前输入文件的名字
FNR: 当前输入文件的记录数目

  1. awk '{print FILENAME, "FNR= ", FNR," NR= ", NR}' student-marks bookdetails
  2. student-marks FNR= 1 NR= 1
  3. student-marks FNR= 2 NR= 2
  4. student-marks FNR= 3 NR= 3
  5. student-marks FNR= 4 NR= 4
  6. student-marks FNR= 5 NR= 5
  7. bookdetails FNR= 1 NR= 6
  8. bookdetails FNR= 2 NR= 7
  9. bookdetails FNR= 3 NR= 8
  10. bookdetails FNR= 4 NR= 9
  11. bookdetails FNR= 5 NR= 10

参考:https://www.runoob.com/linux/linux-comm-awk.html