awk note

处理流程

当使用 awk 命令处理一个或者多个文件时,它会依次读取文件的每一行内容,然后对其进行处理,awk 命令默认从 stdio 标准输入获取文件内容,awk 使用一对单引号来表示一些可执行的脚本代码,在可执行脚本代码里面,使用一对花括号来表示一段可执行代码块,可以同时存在多个代码块。awk 的每个花括号内同时可以有多个指令,每一个指令用分号分隔,awk 其实就是一个脚本编程语言。

格式: awk ‘condition action’ filename

awk -F '[|:;]' '{if ($1 > "m") print $1; else print "---"}' /etc/passwd

脚本化:

#! /bin/awk -f
BEGIN    {print "begin to awk\n"} 
$s ~ /beijing/ 
END { print "end of awk" }

# xxx.awk xxx.data

内置变量

变量含义
$0行内容
$1第一列字段
NF当前行有多少个字段
$NF最后一个字段
NR当前处理的是第几行
FILENAME当前文件名
FS字段分隔符,默认是空格和制表符。
RS行分隔符,用于分割每一行,默认是换行符。
OFS输出字段的分隔符,用于打印时分隔字段,默认为空格。
ORS输出记录的分隔符,用于打印时分隔记录,默认为换行符。
OFMT数字输出的格式,默认为%.6g。

内置函数

func含义
tolower()字符转为小写
length()返回字符串长度
substr()返回子字符串
sin()正弦
cos()余弦
sqrt()平方根
rand()随机数

组合使用

使用 awk 过滤 history 输出,找到最常用的命令

[root@centos ~]# history | awk '{a[$4]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
267 ll
122 vim
118 cd
54 awk
34 man
28 g++
23 rm
21 cat
16 mkdir
13 gcc

过滤文件中重复行

awk '!x[$0]++' <file>

假设有一个文本,每一行都是一个 int 数值,想要计算这个文件每一行的和

awk '{s+=$1} ENG {printf "%.0f", s}' /path/to/file

next

No      Item_Name               Price           Quantity
1       Mangoes                 $3.45              5
2       Apples                  $2.45              25
3       Pineapples              $4.45              55
4       Tomatoes                $3.45              25
5       Onions                  $1.45              15
6       Bananas                 $3.45              30

awk '$4 <= 20 { printf "%s\t%s\n", $0,"*" ; } $4 > 20 { print $0 ;} ' food_list.txt 

No    Item_Name     Price      Quantity
1     Mangoes       $3.45       5    *
2     Apples        $2.45      25
3     Pineapples    $4.45      55
4     Tomatoes      $3.45      25 
5     Onions        $1.45      15   *
6     Bananas       $3.45      30

当第一个表达式用{ printf “%s\t%s\n”, $0,”**” ; }命令进行标注的时候在同样的步骤第二个表达式也进行了判断这样就浪费了时间; 这个东西不是 if else; 而是都判断的,不判断后一个,可以

awk '$4 <= 20 { printf "%s\t%s\n", $0,"*" ; next; } $4 > 20 { print $0 ;} ' food_list.txt

REF