AWK常用(半草稿)

警告
本文最后更新于 2022-06-23,文中内容可能已过时。

https://awk.readthedocs.io/en/latest/chapter-one.html

1. 摘要

awk ' BEGIN{ 语句 } statements2 {语句} END{ 语句 } '

  • BEGIN { 语句 }:在读取任何输入前执行一次 语句
  • END { 语句 }:读取所有输入之后执行一次 语句
  • 表达式 { 语句 }: 对于 表达式 为真(即,非零或非空)的行,执行 语句
  • /正则表达式/ { 语句 }: 如果输入行包含字符串与 正则表达式 相匹配,则执行 语句
  • 组合模式 { 语句 }: 一个 组合模式 通过与(&&),或(||),非(|),以及括弧来组合多个表达式;对于组合模式为真的每个输入行,执行 语句
  • 模式1,模式2 { 语句 }: 范围模式(range pattern)匹配从与 模式1 相匹配的行到与 模式2 相匹配的行(包含该行)之间的所有行,对于这些输入行,执行 语句 。 BEGINEND不与其他模式组合。范围模式不可以是任何其他模式的一部分。BEGINEND是仅有的必须搭配动作的模式。

2. awk 变量

  • $n: 分割后,第n列的字段
  • ${1..n} 代表当前行的1-n的列值
  • $0: 代表整行的数据
  • FS: 表示使用的列的分割符(默认空格,位于BEGIN模块,命令行中-F指定)
  • OFS: 输出列的分割符,默认print $1,$2的时候中间的,代表空格(默认),可使用OFS进行更改,位于BEGIN模块当中
  • NF: 分割后,当前行一共多少个字段($NF最后一列,$(NF-1)倒数第2列)
  • NR: 记录行号,表示当前正在处理的记录的行的号码
  • FNR: 各文件分别计数的行号
  • RS: 表示行分隔符,表示每个记录输入的时候的分割符,即行与行是如何分割的(内置变量RS用来存放输入的记录分割符,可通过BEGIN模块来进行修改,支持正则表达式
  • ORS: 输出记录分隔符(输出换行符),输出时用指定符号代替换行符,默认行的分割符为\n
  • FILENAME: 当前文件名
  • ARGC:命令行参数的个数
  • ARGV: 数组,命令行参数的值
  • RS: 表示行分隔符,表示每个记录输入的时候的分割符,即行与行是如何分割的(内置变量RS用来存放输入的记录分割符,可通过BEGIN模块来进行修改,支持正则表达式

    • 示例 1 :
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      
      [root@00 ~]# head -2 /etc/passwd|awk 'BEGIN{RS=":"}{print NR,$0}'
      ### root:x:0:0:root:/root:/bin/bash  ###
      ### bin:x:1:1:bin:/bin:/sbin/nologin  ###
      1 root
      2 x
      3 0
      4 0
      5 root
      6 /root
      7 /bin/bash  # <<=== 此处本身包含一个换行符
      bin
      8 x
      9 1
      10 1
      11 bin
      12 /bin
      13 /sbin/nologin
      
    • 示例 2 :
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      
      [root@00 ~]# head -n 3 /etc/passwd|awk 'BEGIN{RS="[:/0-9]+|\n"}{print $0}' |sort|uniq -c
      ### root:x:0:0:root:/root:/bin/bash         ###
      ### bin:x:1:1:bin:/bin:/sbin/nologin        ###
      ### daemon:x:2:2:daemon:/sbin:/sbin/nologin ###
          1 bash
          4 bin
          2 daemon
          2 nologin
          3 root
          3 sbin
          3 x
      
  • FS: 输入分割符,命令处理参数使用-F指定分割符,或者使用变量形式修改

    • 示例:
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      
          $> awk -F ":" 'NR==12,NR==15{print NR,$1,$3}' pwd.txt 
          12 ftp 14
          13 nobody 65534
          14 systemd-coredump 999
          15 systemd-network 192
      
          $> awk -v FS=":" 'NR==12,NR==15{print NR,$1,$3}' pwd.txt 
          12 ftp 14
          13 nobody 65534
          14 systemd-coredump 999
          15 systemd-network 192
      
          $>  head -1 passwd |awk 'BEGIN{FS=":"}{print $1,$2}'
          ### root:x:0:0:root:/root:/bin/bash         ###
          root x
      
  • OFS: 输出分割符,使用OFS变量进行修改

    • 示例:
      1
      2
      3
      4
      5
      
          $> awk -F ":" -v OFS="--" 'NR==12,NR==15{print NR,$1,$3}' pwd.txt 
          12--ftp--14
          13--nobody--65534
          14--systemd-coredump--999
          15--systemd-network--192
      
  • 其他示例

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    # 打印范围 
    $> awk -F: 'NR==12,NR==15{print NR,$1,$3}' pwd.txt 
    12 ftp 14
    13 nobody 65534
    14 systemd-coredump 999
    15 systemd-network 192
    
    # 自定义变量 
    awk -v param=n_user 'BEGIN{print "当前用户: " param}'
    当前用户: n_user
    $> param=$(whoami)
    $> echo $param
    cxd
    $> awk -v param=$param 'BEGIN{print "当前用户: " param}'
    当前用户: cxd
    

3. 域

  • awk 默认分割符为空格,或者连续的空格,tab默认也为(连续)空格
  • awk中只存在条件时,默认输出整行

4. 正则匹配

  • 搜索/etc/passwd中用户主目录在root下的用户名和bash
  • 变量~正则 表示变量值匹配正则表达式
  • 变量!~正则 表示变量值不匹配正则表达式
1
2
3
4
5
[root@00 ~]# awk -F: '$(NF-1)~/^\/root/{print $1,$NF}' /etc/passwd  
### root:x:0:0:root:/root:/bin/bash              ###
### operator:x:11:0:operator:/root:/sbin/nologin ###
root /bin/bash
operator /sbin/nologin

5. BEGIN and END

BEGIN{变量定义} {判断和计算} END{判读和计算完结执行操作}

1
seq 100 | awk 'BEGIN{sum=0}{sum=$0+sum}END{print sum}'
  • 示例:
1
2
3
4
5
6
$> awk -F: 'BEGIN{printf "%-25s\t%-25s\t%-25s\t\n","用户名","UID","GID"}NR==2,NR==5{printf "%-25s\t%-25s\t%-25s\n",$1,$3,$4}' pwd.txt 
用户名                       UID                       	 GID                      	
bin                      	1                        	1                        
daemon                   	2                        	2                        
adm                      	3                        	4                        
lp                       	4                        	7  
1
2
3
4
5
6
7
awk '
BEGIN { actions } 
/pattern/ { actions }
/pattern/ { actions }
……….
END { actions } 
' filenames 

6. awk 数组

类似key=value

7. awk 循环

foreach 循环