Linux的awk详细用法

1,653 阅读2分钟

awk的基本概念

  • awk主要是用于进行数据切片

  • awk缺省的行分隔符是换行,缺省的列分隔符是连续的空格和tab,行分隔符和列分隔符都可以自定义

  • awk命令行的基本形式

    awk option 'script' file1 file2 ...
    awk option -f scriptfile file1 file2 ...
    
  • awk命令的基本格式

    awk [options] 'Pattern{Action}' file
    awk /pattern/ {actions}
    awk /condition/ {actions}
    

    pattern是正则表达式,actions是匹配成功后的一系列操作。awk程序一行一行读出待处理文件,如果某一行与pattern匹配,或者满足condition条件,则执行相应的actions;如果缺省pattern,则actions作用于文件的每一行

  • awk的基本语法

    awk [options] 'Pattern{Action}' file

    [options]: 运行的一些参数项,可以省略

    Pattern{Action}:是命令主要部分,其中Action是核心操作,Parttern有时可以省略。

    file: 用于指定我们操作的格式化文本的名字,可以同时操作多个文件。

awk命令

数据准备

  1. touch test_ip.txt
  2. vim test_ip.txt
    IP Port Num
    127.0.0.1 22 12
    192.178.1.1 23 1
    127.0.0.1 23 12
    127.0.0.1 22 33
    127.0.0.1 21
    

action

  • print命令:打印;要结合{}一起使用
  • $0: 结合print一起使用,0表示打印全部;1表示打印第一列(按照列分隔符);2表示打印第二列;依次类推
  • awk '{print $0}' test_ip.txt,打印全部内容
  • awk '{print $1}' test_ip.txt, 打印第一列内容
  • action内被双引号包裹的信息,会被当作字符串输出

pattern

  1. 模式
    • BEGIN模式:指定处理文本之前需要执行的操作
    • END模式:指定处理文本之后需要执行的操作
  2. 命令
    • awk 'BEGIN{print "IP地址", "端口号"}{print $1, $2}' test_ip.txt
    • awk '{print $1, $2}END{print "IP地址", "端口号"}' test_ip.txt

option

  1. 参数
    • FS: 输入分隔符;用于指定输入的格式文本时,按照何种分隔符进行列的划分
    • OFS: 输出分隔符;用于输出格式文本的时候,用何种分隔符进行列的划分。
    • -F: 指定列分隔符
    • -v: 设置变量
  2. 命令
    • 指定列分隔符为:,并打印第一列
      • awk -F '.' '{print $1}' test_ip.txt

      • awk -v FS="." '{print $1}' test_ip.txt

    • 指定输出分隔符为#,并打印第一和第二列
      • awk -v OFS="#" '{print $1, $2}' test_ip.txt

变量

  1. 内置变量
    • FS: 输入字段分隔符,默认为空白字符
    • OFS: 输出字段分隔符,默认为空白字符
    • RS: 输出记录分隔符(输入换行符),指定输入时的换行符
    • ORS: 输出记录分隔符(输出换行符),输出时用指定符号代替换行符
    • NF: 当前行的字段的个数(即当前行被分割成了几列),字段数量
    • NR: 行号,当前处理的文本行的行号
    • FNR: 各文件分别计数的行号
    • FILENAME: 当前文件名
    • ARGC: 命令行参数的个数
    • ARGV: 数组,保存得失命令行所给定的各参数

awk案例

B站非常好的一个案例视频

  1. a b c db后面插入三个字段"e f g"

    echo "a b c d" | awk '$3="e f g"{print $0}'
    
  2. 格式化空白;移除每行的前缀、后缀空白,并将各部分左对齐

            aaaa     bbbb   cc
      bbb aaa ccc
    ddd       ffff          eee gg gg dd
    

    awk -v OFS="\t" '{$1=$1;print $0}' test.txt

    -t表示制表符; $1=$1的逻辑表示根据OFS的值重建$0(修改字段或者修改NF的值都会导致$0重建)

  3. 从ifconfig命令的结果中筛选出除了io网卡外的所有ipv4地址

    ifconfig | awk '/inet / && !($2 ~ /^127/) {print$2}'
    
  4. 读取.ini配置文件中的某段

    test_ini.txt内容

    [base]
    this is base
    hello
    
    
    [mysql]
    this is mysql
    say mysql
    
    
    
    [python]
    this is python
    say python
    

    查询mysql那一段

    解一:
    awk '/mysql/, !/\[.*\]/' test_ini.txt
    
    解二:
    1.awk 文件
    index($0, "[mysql]"){
    print
    while ((getline var) > 0){
    if (var ~ /\[.*\]/){
    	exit
    }
    print var
    }
    }
    命令:awk -f 1.awk test_ini.txt
    
  5. 根据某字段去重

    1.txt

    2019-01-13_12:00_index?uid=123
    2019-01-13_13:00_index?uid=123
    2019-01-13_14:00_index?uid=123
    2019-01-13_12:00_index?uid=9710
    2019-01-13_12:00_index?uid=333
    

    命令:awk -F "?" '{arr[$2]=arr[$2]+1;if(arr[$2]==1){print}}' 1.txt

  6. 次数统计

    awk -F "?" '{arr[$2]=arr[$2]+1}END{for( i in arr){print arr[i], i}}' 1.txt

  7. 统计TCP连接状态数量

    netstat | awk '/^tcp/{arr[$6]=arr[$6]+1}END{for(i in arr){print arr[i], i}}'
    
  8. 统计独立IP

    1.txt

    a.com.cn|202.109.134.123
    b.com.cn|202.109.134.123
    a.com.cn|202.109.134.124
    a.com.cn|202.109.134.125
    b.com.cn|202.109.134.124
    a.com.cn|202.109.134.123
    

    1.awk

    BEGIN{
      FS="|"
    }
    {
       if(!arr[$1,$2]++){
         arr1[$1]++
    }
    }
    END{
     for( i in arr1){
       print i, arr1[i]
    }
    }
    

    命令:awk -f 1.awk 1.txt

  9. 处理字段缺失的数据

    1.txt

    ID  name   gender  age  email         phone
    1   Alice  female  28   abc@qq.com    110
    2   Bob            20   def@qq.com    
    3   tony   male    21   11111@qq.com  130
    4   alex   male    22                 140
    

    1.awk

    BEGIN{
      FIELDWIDTHS="2 7 8 5 14 7"
    }
     {
      print $4,$5,$6
    }
    # FIELDWIDTHS 设置每列的字符数,假设不存在内容,会强制写空字符;上面也可以写成FIELDWIDTHS="2 2:5 2:6 2:3 3:12 2:5"
    

    命令:awk -f 1.awk 1.txt

  10. 处理字段中包含了字段分隔符的数据

    echo 'robbins,arnold,"1234 A pretty street, Ne",myTown,mystates,12345-6789,usa' | awk 'BEGIN{FPAT="[^,]+|\".*\""}{print $1,$3}'
    

    取第三列

  11. 取字段中指定字符数量

    取第一个字段,和第二个字段前三位

    echo '16 001agdcdafasd' | awk '{print $1,substr($2,1,3)}'
    
    
    echo '16 001agdcdafasd' | awk 'BEGIN{FIELDWIDTHS="2 2:3"}{print $1,$2}'