参考资料
目录
一. 配置项
1.1 基本参数
-F
:指定字段分隔符。
awk -F',' '{ print $1 }' file
使用逗号作为分隔符。-f
:指定包含awk脚本的文件。
awk -f handle.awk file
使用 handle.awk 文件中的脚本。-v
:定义变量并为其赋值。
awk -v var=10 '{ print var }' file
设置变量 var 的值为 10。BEGIN{}
:初始化代码块,在对每一行进行处理之前,初始化代码。
主要是引用全局变量,设置FS分隔符等。//
:匹配用的代码块,可以是字符串或正则表达式。{}
:命令代码块,多个命令之前使用;
来分隔。END{}
: 结尾代码块,在对每一行进行处理之后再执行的代码块。
主要是进行最终计算或输出结尾摘要信息
awk [-F|-f|-v] 'BEGIN{} // {command1; command2} END{}' ./path/filename
1.2 内置变量
内置变量 | 英文全称 | 说明 | 默认值 |
---|---|---|---|
$0 | 整个内容 | ||
$n | 每行的第n个字段 | ||
FILENAME | 文件名 | “-” | |
RS | Record Separator | 行的分隔符 | 换行符(\n) |
FS | Field Separator | 字段的分隔符 | 空格 |
ORS | Output Record Separator | 输出行的分隔符 | 换行符(\n) |
OFS | Output Field Separator | 输出字段的分隔符 | 空格 |
NR | Number of Records | 正在处理的行数 | |
NF | Number of Fields | 正在处理的字段数 | |
$NF | 当前行最后一个字段 | ||
$(NF-1) | 当前行倒数第二个字段 |
1.3 内置函数
函数名 | 说明 |
---|---|
sub(regex, sub, string) | 字符串替换 |
substr(str, start, l) | 字符串切割 |
length(String) | 获取字符串长度 |
split(String, A, [Ere]) | 字符串分割 |
tolower(String) | 转小写 |
toupper(String) | 转大写 |
二. 配置项示例
2.1 -F 字段分隔符
2.1.1 指定1个字段分隔符
⏹ price.txt
香蕉,100,越南
苹果,200,柬埔寨
菠萝,500,菲律宾
- 使用
,
作为字段分隔符,香蕉等水果就是第一个字段,因此是$1
。
awk -F"," '{print $1}' ./price.txt
2.1.2 指定2个字段分隔符
-F"[,_]"
:中括号内部存放字段分隔符
awk -F"[,_]" '{print $3}'
2.1.3 $1与$3相连输出,不分隔
awk -F":" '{print $1 $3}' /etc/passwd
2.1.4 $1与$3使用空格分隔
awk -F":" '{print $1,$3}' /etc/passwd
2.1.5 $1与$3之间手动添加空格分隔
awk -F":" '{print $1 " " $3}' /etc/passwd
2.1.6 自定义输出
awk -F":" '{print "Username:" $1 "\t\t Uid:" $3 }' /etc/passwd
2.1.7 显示每行有多少字段
awk -F: '{print NF}' /etc/passwd
2.1.8 将每行最后一个字段打印出来
{print $NF}
:动作语句,告诉 awk 要对每一行执行的操作。$NF
:这里的$
符号用于引用字段,NF
是 awk 中的一个内置变量,表示当前记录中的字段数。
$NF
表示当前记录中的最后一个字段。
awk -F: '{print $NF}' /etc/passwd
2.1.9 显示只有4个字段的行
awk -F: 'NF==4 {print }' /etc/passwd
2.1.10 显示每行字段数量大于2的行
awk -F: 'NF > 2 {print $0}' /etc/passwd
2.2 -v 定义变量
⏹ file1.txt
- 字段之间使用 TAB 作为分隔符。
贾飞天 18
张三 16
李四 25
- 通过 -F 显示指定字段分隔符为 TAB
- 通过 -v 定义一个变量count,值为 10
cat file1.txt | awk -F"\t" -v count=10 '{print $1, $2 + count}'
2.3 // 匹配
⏹ file2.txt
2323 SEQIN mmm isuuePayId=5768awe uuid=woenoo; jmw_state=success method=paypay info=ppp
2323 SEQOUT COST=45726
2345 SEQIN mmm isuuePayId=34895ry uuid=;ljkler jmw_state=faile method=alipay info=ddd
2345 SEQOUT COST=34855
⏹ file3.txt
2323,SEQIN,mmm,isuuePayId=5768awe,uuid=woenoo;,jmw_state=success,method=paypay,info=ppp
2323,SEQOUT,uuaa=5768,COST=45726
2345,SEQIN,mmm,isuuePayId=34895ry,uuid=;ljkler,jmw_state=faile,method=alipay,info=ddd
2345,SEQOUT,COST=34855
2.3.1 行包含与不包含
⏹ 查询包含COST的行
cat file2.txt | awk '/COST/ {print $0}'
⏹ 查询不包含SEQOUT的行
cat file2.txt | awk '!/SEQOUT/ {print $0}'
2.3.2 &&
行同时包含多个关键字
⏹查询同时包含isuuePayId和success的行
cat file2.txt | awk '/isuuePayId/ && /success/ {print $0}'
2.3.3 ||
行包含关键字1或关键字2
⏹查询包含isuuePayId或2323的行
cat file2.txt | awk '/isuuePayId/ || /2323/ {print $0}'
2.3.4 ^
行头与$
行尾
⏹ 查询行头为2345的行
cat file2.txt | awk '/^2345/ {print $0}'
⏹ 查询行尾为ppp的行
cat file2.txt | awk '/ppp$/ {print $0}'
2.3.5 指定字段包含/不包含关键词
⏹ 查询第四个字段包含5768的行
cat file3.txt | awk -F"," '$4~/5768/ {print $0}'
⏹ 查询第四个字段不包含5768的行
cat file3.txt | awk -F"," '$4!~/5768/ {print $0}'
2.4 {} 代码块
2.4.1 IF 语句
- 必须用在
{}
中,且比较内容用()
包裹起来 if
必须是小写,不是大写
⏹ 查询第4个字段包含5768的行,并且第5个字段等于uuid=woenoo;的行
cat file3.txt | awk -F"," '{if($4~/5768/ && $5=="uuid=woenoo;") print $0}'
2.4.2 BEGIN{},END{}代码块
⏹ file4.txt
姓名,成绩
贾飞天,100
张三,80
李四,70
王五,59
赵六,82
王七,73
NR>1
:跳过第一行(因为第一行是标题)- 在
BEGIN{}
代码块里面定义变量 - 在
普通{}
里面进行累加 - 在
END{}
代码块里对最终的结果进行格式化输出 %d
:用于代表字符串变量的占位符\n
:换行符END{print "优秀人数:" excellent, "\n","普通人数:" common, "\n", "成绩差人数:" bad}'
如果用这种方式写的话,输出的结果虽然也能换行,但是从第二行开始左边会多一个空格。
因为print语句在awk中默认使用空格作为字段分隔符。
cat file4.txt | awk -F"," 'BEGIN{excellent=0;common=0;bad=0} NR>1
{
if($2 >= 80) {excellent++}
else if($2 >= 60 && $2 < 80) {common ++}
else {bad++}
}
END{printf "成绩优秀人数:%d\n成绩普通人数:%d\n成绩差人数:%d\n", excellent, common, bad}'
2.5 FS,RS
2.5.1 FS 指定字段分隔符
FS
和-F
的作用相同,都用来指定字段分隔符。FS
一般在BEGIN{}
代码块中使用。- 如果需要指定多个字段分隔符的话,使用
FS="[,_]"
# 指定一个分隔符
echo "贾飞天,张三,李四" | awk 'BEGIN{FS=","} {print $3}'
# 指定两个分隔符
echo "贾飞天,张三_李四" | awk 'BEGIN{FS="[,_]"} {print $3}'
2.5.2 RS 指定换行符
⏹ file5.txt
Alice,25
Bob,30
Charlie,22
printf "%s,\n"
:%s
表示整行,整个打印语句表示给整行后加上逗号和换行符\nRS=","
:表示用逗号作为换行符,可以看到由于行后面也加了逗号,所以边行变列,都变为一行了。
cat file5.txt | awk '{printf "%s,\n", $0}' | awk 'BEGIN{RS=","} {print $1}'
2.6 OFS 输出字段分隔符
⏹ file6.txt
线程号,唯一标识,支付方式,结果
110120,uuid=1234,pay=123alipay,result=success
256754,uuid=2332,pay=344alipay,result=fail
234556,uuid=7456,pay=869paypay,result=success
BEGIN{FS=","}
:使用,
作为字段分隔符NR==1 || $3~/alipay/
:输入第1行或者第3个字段包含alipay的行print NR, $1, (NR == 1 ? $3 : substr($3, 5, length($3) - 4))
print NR, $1
:打印行号,第1个字段NR == 1 ? $3 : substr($3, 5, length($3) - 4)
:若是第一行,则直接打印第3个字段
若不是第一行,则将第3个字段从第5位开始截取到最后
OFS="_"
:输出的字段通过_
来连接
cat file6.txt | awk 'BEGIN{FS=","} NR==1 || $3~/alipay/
{
print NR, $1, (NR == 1 ? $3 : substr($3, 5, length($3) - 4))
}'
OFS="_"
2.7 NR 行数
2.7.1 只输出奇数行
ls -l ~/uwsgi-2.0.18/core/m*.c | awk 'NR % 2 == 1 {print "第"NR"行", $0}'
2.7.2 只输出第三行以后的行
ls -l ~/uwsgi-2.0.18/core/m*.c | awk 'NR > 3 {print "第"NR"行", $0}'
2.7.3 输出每行的行号
awk '{print NR,$0}' /etc/passwd
2.7.4 依次打印行号,字段数,最后字段值,制表符,每行内容
awk -F: '{print NR, NF, $NF, "\t", $0}' /etc/passwd
2.7.5 显示第5行
awk -F: 'NR==5{print}' /etc/passwd
2.7.6 显示第5行和第6行
awk -F: 'NR==5 || NR==6 {print}' /etc/passwd
2.7.7 不显示第一行
route -n | awk 'NR! = 1 {print}'
三. 内置函数
3.1 gsub() 替换全部匹配到的字符串
⏹ fruit.txt
日本苹果,100,uuid=1223
中国苹果,200,uuid=3434
越南苹果,59,uuid=2898
梨,50,uuid=8976
西瓜,56,uuid=9079
BEGIN{FS=","}
:使用,
作为分隔符$1~/苹果/ && $2 > 99
:条件为第1个字段包含苹果,且第2个字段 > 99gsub("苹果","★苹果",$1);
:将苹果替换为★苹果
# 下面这两种写法相同
cat fruit.txt | awk 'BEGIN{FS=","} $1~/苹果/ && $2 > 99 {gsub("苹果","★苹果",$1); print $0}'
# ★& 中的 & 就代表匹配到的内容
cat fruit.txt | awk 'BEGIN{FS=","} $1~/苹果/ && $2 > 99 {gsub("苹果","★&",$1); print $0}'