Linux awk命令(1)

124 阅读5分钟

Linux awk命令

作用

文本格式化

语法

awk options 'pattern {action}' file

选项的参数解释

  • options:选项,用于控制 awk 的行为。

  • pattern:是用于匹配输入数据的模式。如果省略,则 awk 将对所有行进行操作。

  • {action}:是在匹配到模式的行上执行的动作。如果省略,则默认动作是打印整行

    options参数说明:

    • -F <分隔符> 或 --field-separator=<分隔符>:指定输入字段的分隔符,默认就是空格。
    • -v <变量名>=<值>:设置awk内部的值,可使用该选项将外部值传递给awk脚本中的变量。
    • -f <脚本文件>:指定一个awk脚本文件。我们可以在指定文件中编写一个较大的awk脚本,然后通过-f 加载该脚本
    • -V或者--version:显示awk的版本信息。
    • -h 或者--help:显示 awk 的帮助信息,包括选项和用法示例。

    以下是一些awk的常见用法:

    打印整行:

    awk '{print}' file
    

    打印特定列:

    awk '{print $1, $2}' file
    
    [root@kylin awk]# awk '{print $1, $2}' awktest.txt 
    asda adfsff
    asdas sdvgs
    njnk hsdh
    asdasdal adkl
    

    使用分隔符指定列:

    awk -F ' ' '{print $1, $2}' file
    
    [root@kylin awk]# awk -F ' ' '{print $1, $3}' awktest.txt
    asda jppop
    asdas dsadfsdf
    njnk ipp
    asdasdal asdqvv
    

    打印行数:

    awk '{print NR, $0}' file
    
    [root@kylin awk]# awk '{print NR, $0}' awktest.txt 
    1 asda adfsff jppop fdsd
    2 asdas sdvgs dsadfsdf
    3 njnk hsdh ipp fcsadfsdf gfgfgdfga
    4 asdasdal adkl asdqvv tthgf
    

    打印满足条件的行

    awk '/pattern/ {print NR, $0}' file
    

    如果我想找出包含 “njnk” 的行,以及行号

    [root@kylin awk]# awk '/njnk/ {print NR, $0}' awktest.txt 
    3 njnk hsdh ipp fcsadfsdf gfgfgdfga
    

    计算列的总和

    awk 'END {print NR}' file
    
    [root@kylin awk]# awk 'END{print NR}' awktest.txt
    4
    

    打印最大值(第一列)

    awk 'max < $1 {max = $1} END {print max}' file
    
    awk 'BEGIN {max=-INF} {if ($1>max) max=$1} END {print max}' file
    

    初始化 max 变量为无穷小 -INF-INFawk 中表示负无穷大的特殊值,这保证了任何数值都会大于它,从而允许第一次遇到的数值成为新的最大值。

    [root@kylin awk]# awk 'max < $1 {max = $1} END {print max}' awktest.txt 
    njnk
    [root@kylin awk]# awk 'BEGIN {mak=-INF} {if ($1>max) max=$1} END {print max}' awktest.txt 
    njnk
    

    格式化输出:

    awk '{printf "%-10s %-10s\n", $1, $2}' file
    
    [root@kylin awk]# awk '{printf "%-10s %-10s\n", $1, $2}' awktest.txt 
    asda       adfsff    
    asdas      sdvgs     
    njnk       hsdh      
    asdasdal   adkl
    

基本用法

log.txt 文本内容:

ni yao gan sha 4
3 awk grep sed
who's a cool man
919 There are postgresql,mysql,gaussdb

用法1:

awk '{[pattern] action}' {filenames}   # 行匹配语句 awk '' 只能用单引号

每行按空格或TAB分割,输出文本中的1、4项

[root@kylin awk]# awk '{print $1,$4}' log.txt 
ni sha
3 sed
who's man
919 postgresql,mysql,gaussdb

格式化输出

[root@kylin awk]# awk '{printf "%-10s %30s\n",$1,$4}' log.txt 
ni                                    sha
3                                     sed
who's                                 man
919              postgresql,mysql,gaussdb
  • "%-10s" : 这是一个格式控制字符串,用于指定第一个输出字段的格式。%-10s 表示输出一个字符串,占据10个字符宽度,左对齐(- 表示左对齐)。如果字符串长度小于10,剩余的空间会被填充为默认的空格。
  • %30s: 类似地,这表示输出第二个字段,占据30个字符宽度,右对齐(默认情况下 printf 是右对齐的)。如果字符串长度小于30,右侧会被填充为空格。
  • \n: 这是一个换行符,用于在输出完一行数据后开始新的一行。

用法2:

awk -F  #-F相当于内置变量FS, 指定分割字符

使用","分割

[root@kylin awk]# awk -F, '{print $1,$2}' log.txt 
ni yao gan sha 4 
3 awk grep sed 
who's a cool man 
919 There are postgresql mysql

或者使用内置变量

[root@kylin awk]# awk 'BEGIN{FS=","} {print $1,$2}' log.txt 
ni yao gan sha 4 
3 awk grep sed 
who's a cool man 
919 There are postgresql mysql

使用多个分隔符.先使用空格分割,然后对分割结果再使用","分割

[root@kylin awk]#  awk -F '[ ,]'  '{print $1,$2,$4}'   log.txt
ni yao sha
3 awk sed
who's a man
919 There postgresql

用法3:

awk -v  # 设置变量
[root@kylin awk]# awk -va=1 '{print $1,$1+a}' log.txt
ni 1
3 4
who's 1
919 920
[root@kylin awk]# awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt
ni 1 nis
3 4 3s
who's 1 who'ss
919 920 919s

用法4:

awk -f {awk脚本} {文件名}
 $ awk -f cal.awk log.txt
[root@kylin awk]# cat cal.awk 
{print $1}
[root@kylin awk]# awk -f cal.awk log.txt 
ni
3
who's
919

运算符

运算符描述
= += -= *= /= %= ^= **=赋值
?:C条件表达式
||逻辑或
&&逻辑与
~ 和 !~匹配正则表达式和不匹配正则表达式
< <= > >= != ==关系运算符
空格连接
+ -加,减
* / %乘,除与求余
+ - !一元加,减和逻辑非
^ ***求幂
++ --增加或减少,作为前缀或后缀
$字段引用
in数组成员

过滤第一列大于3的行

awk '$1 > 3' 
[root@kylin awk]# awk '$1 > 3' log.txt 
ni yao gan sha 4
who's a cool man
919 There are postgresql,mysql,gaussdb

过滤第一列等于3的行

[root@kylin awk]# awk '$1 == 3' log.txt 
3 awk grep sed

过滤第一列大于3并且第二列等于'There'的行

[root@kylin awk]# awk '$1>3 && $2=="There" {print $0}' log.txt 
919 There are postgresql,mysql,gaussdb

内建变量

变量描述
$n当前记录的第n个字段,字段间由FS分隔
$0完整的输入记录
ARGC命令行参数的数目
ARGIND命令行中当前文件的位置(从0开始算)
ARGV包含命令行参数的数组
CONVFMT数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO最后一个系统错误的描述
FIELDWIDTHS字段宽度列表(用空格键分隔)
FILENAME当前文件名
FNR各文件分别计数的行号
FS字段分隔符(默认是任何空格)
IGNORECASE如果为真,则进行忽略大小写的匹配
NF一条记录的字段的数目
NR已经读出的记录数,就是行号,从1开始
OFMT数字的输出格式(默认值是%.6g)
OFS输出字段分隔符,默认值与输入字段分隔符一致。
ORS输出记录分隔符(默认值是一个换行符)
RLENGTH由match函数所匹配的字符串的长度
RS记录分隔符(默认是一个换行符)
RSTART由match函数所匹配的字符串的第一个位置
SUBSEP数组下标分隔符(默认值是/034)
[root@kylin awk]# awk 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s \n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "-------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' log.txt 
FILENAME ARGC  FNR   FS   NF   NR  OFS  ORS   RS 
-------------------------------------------
log.txt    2    1         5    1         
    
​
log.txt    2    2         4    2         
    
​
log.txt    2    3         4    3         
    
​
log.txt    2    4         4    4
[root@kylin awk]# awk -F^ 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s \n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "-------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' log.txt 
FILENAME ARGC  FNR   FS   NF   NR  OFS  ORS   RS 
-------------------------------------------
log.txt    2    1    ^    1    1         
    
​
log.txt    2    2    ^    1    2         
    
​
log.txt    2    3    ^    1    3         
    
​
log.txt    2    4    ^    1    4

正则表达式

# 输出第二列包含 "a",并打印第二列与第四列
[root@kylin awk]# awk '$2 ~ /a/ {print $2,$4}' log.txt 
yao sha
awk sed
a man

~ 表示模式开始。// 中是模式

awk 脚本

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

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

创建测试文件如下:

Marry 2143 78 84 77 Jack 2321 66 78 45 Tom 2122 48 77 71 Mike 2537 87 97 95 Bob 2415 40 57 62

cal.awk脚本如下:

[root@kylin awk]# cat cal.awk 
#!/bin/awk -f
BEGIN {
        math = 0
        english = 0
        computer = 0
​
        print "NAME     NO      MATH    ENGLISH         COMPUTER        TOTAL\n"
        print "--------------------------------------------------------------\n"
}
{
        math+=$3
        english+=$4
        computer+=$5
        printf "%-6s %-6s %4d %8d %8d %8d\n",math,english,computer      
}
END {
        print "--------------------------------------------------------------\n"
        printf "  TOTAL:%10d %8d %8d \n", math, english, computer
        printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}

执行结果

[root@kylin awk]# awk -f cal.awk score.txt 
NAME    NO      MATH    ENGLISH         COMPUTER        TOTAL

--------------------------------------------------------------

Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
--------------------------------------------------------------

  TOTAL:       319        0      350 
AVERAGE:     63.80     0.00    70.00
[root@kylin awk]# vim cal.awk 
[root@kylin awk]# awk -f cal.awk score.txt 
NAME    NO      MATH    ENGLISH         COMPUTER        TOTAL

--------------------------------------------------------------

Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
--------------------------------------------------------------

  TOTAL:       319      393      350 
AVERAGE:     63.80    78.60    70.00