文章目录
awk 概述
AWK是一种优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言的最大功能取决于一个人所拥有的知识。awk命名:Alfred Aho Peter 、Weinberger和brian kernighan三个人的姓的缩写。
awk---->gawk 即: gun awk
在linux上常用的是gawk,awk是gawk的链接文件
man gawk---->pattern scanning and processing language模式扫描和处理语言。
pattern [pætn] 模式 ; process[prəʊses]处理
任何awk语句都是由模式和动作组成,一个awk脚本可以有多个语句。模式决定动作语句的触发条件和触发时间。
模式:
正则表达式 :/root/ 匹配含有root的行 /*.root/
关系表达式: < > && || + ***
匹配表达式: ~ !~
动作:
变量 命令 内置函数 流控制语句
它的语法结构如下:
awk [options] 'BEGIN{ print “start” }pattern{ commands }’END{ print “end” }'file
其中:BEGIN END是AWK的关键字部,因此必须大写;这两个部分开始块和结束块是可选的
awk 的巩工作模式
和sed 命令类似,从上向下一次遍历
语法格式:
- awk ‘BEGIN{}parttern{commands} END{}’ file——name
- stabdard output (标准输出) |awk ‘BEGIN{} pattern{commands}END{}’
语法格式说明:
BEGIN{}:正式处理数据之前执行
pattern 匹配模式
{commands} 处理命令,可能多行
END{} 处理玩所有匹配数据后执行
awk 的内置变量
内置变量 | 含义 |
---|---|
$0 | 打印整行内容 |
n | 打印当前行的第1-n个字段 |
NF | 当前行的字段个数,也就是有多少列 |
NR | 当前行的行号,从1开始计数 |
FNR | 多文件处理时,每个文件行号单独计数,都是从0 开始 |
FS | 输入字段分割符,不指定默认以空格或tab键分割 |
RS | 输入行分割符,默认回车换行 |
OFS | 输入字段分割符,默认为空格 |
ORS | 输出行分割符,默认为回车换行 |
FILENAME | 处理文件的文件名 |
ARGC | 命令行参数个数 |
ARGV | 命令行参数数组 |
- $0 打印整行内容
[root@localhost ~]# awk '{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
……
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
[root@localhost ~]#
[root@localhost ~]# awk 'BEGIN{FS=":"} {print $1}' /etc/passwd #以:分隔符,打印第一字段
root
bin
daemon
adm
……
sshd
postfix
[root@localhost ~]#
[root@localhost ~]# awk 'BEGIN{FS=":"} {print $2}' /etc/passwd
#打印/etc/passwd 文件的第二个字段
x
x
x
……
x
x
[root@localhost ~]#
# 打印每一行的第7个字段
[root@localhost ~]# awk 'BEGIN{FS=":"} {print $7}' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
……
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
[root@localhost ~]#
## 默认是以空格键和tab键 为分隔符。如果不需要特定指定分隔符,就不需要加'BEGIN{FS="分隔符"}'
[root@hbs ~]# cat list
Hadoop Spark Flume
Java Python Scala
Allen Mike Meggie
[root@hbs ~]#
[root@hbs ~]# awk '{print $1}' list
Hadoop
Java
Allen
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{FS=":"} {print $NF}' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
……
# $NF 通常可以表示一行的最大值,最后一个数
- NF 当前行的字段个数,也就是有多少列
[root@hbs ~]# vim list
[root@hbs ~]# cat list
Hadoop Spark Flume #这行有3个字段
Java Python Scala GO #这行有4个字段 #tab键 没有哦占用啊
Allen Mike Meggie #这行有3个字段
[root@hbs ~]#
[root@hbs ~]# awk '{print NF}' list
3
4
3
[root@hbs ~]#
[root@hbs ~]# awk '{print NR}' list #输出行号有哪些
1
2
3
[root@hbs ~]#
#当接多个文件后,发现他是累计计算的,so出现等多个文件就会单独计数FNR
[root@hbs ~]# awk '{print NR}' list /etc/passwd
1
2
3
4
5
6
7
……
21
[root@hbs ~]#
[root@hbs ~]# awk '{print FNR}' list /etc/passwd list和/etc/passwd 单独计数
1
2
3
1
2
3
4
……
17
18
[root@hbs ~]#
- FS 输入字段分割符,不指定默认以空格或tab键分割
[root@hbs ~]# vim list
[root@hbs ~]# cat list
Hadoop|Spark:Flume
Java|Python:Scala:GO
Allen|Mike:Meggie
[root@hbs ~]# awk '{print $2}' list #默认以空格为分隔符,所以没显示
[root@hbs ~]#
#以|符分隔 ‘BEGIN{FS="分割符"} {print $n}’ file
[root@hbs ~]# awk 'BEGIN{FS="|"} {print $1}' list
Hadoop
Java
Allen
[root@hbs ~]#
#以 : 分割 字段
[root@hbs ~]# awk 'BEGIN{FS=":"} {print $2}' list
Flume
Scala
Meggie
[root@hbs ~]#
- RS 输入行分割符,默认回车换行 默认是回车,如果不是回车,自定义的话需要RS 指定
[root@hbs ~]# cat tianzhen
Hadoop|Spark|Flume---java|Python|Scala|Go---Allen|Mike|Meggie
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{RS="---"} {print $0}' tianzhen
Hadoop|Spark|Flume
java|Python|Scala|Go
Allen|Mike|Meggie
[root@hbs ~]#
#先以行显示,在以|分割
[root@hbs ~]# awk 'BEGIN{RS="---";FS="|"} {print $3}' tianzhen
Flume
Scala
Meggie
[root@hbs ~]#
- ORS 输出行分割符,默认为回车换行
[root@hbs ~]# awk 'BEGIN{RS="---";FS="|";ORS="****"} {print $3}' tianzhen
Flume****Scala****Meggie
****[root@hbs ~]#
- OFS
[root@hbs ~]# awk 'BEGIN{RS="***"};FS="---";OFS=":" {print $1,$3}' tianzhen
Hadoop|Spark|Flume---java|Python|Scala|Go---Allen|Mike|Meggie
Hadoop|Spark|Flume---java|Python|Scala|Go---Allen|Mike|Meggie:
[root@hbs ~]#
# 一般写脚本时候,不会常用这三个
- FILENAME 处理文件的文件名
[root@hbs ~]# awk '{print FILENAME}' tianzhen (文件名)
tianzhen
tianzhen
tianzhen
[root@hbs ~]#
[root@hbs ~]# awk '{print FILENAME}' list (文件名)
list
list
list
[root@hbs ~]#
awk 格式化输出值printf
格式化 | 含义 |
---|---|
%s | 打印字符串 |
%d | 打印十进制数字 |
%f | 打印一个浮点数 |
%x | 打印十六进制数 |
%o | 打印八进制数字 |
%e | 打印数字科学技术法形式 |
%c | 打印单个字符的ASCII码 |
printf 默认是没有换行格式的
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf $1}' /etc/passwd
rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodysystemd-networkdbuspolkitdsshdpostfix[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s\n",$1}' /etc/passwd
root
bin
daemon
……
sshd
postfix
[root@hbs ~]#
#打印第一个和第7个字段
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s %s\n",$1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
……
sshd /sbin/nologin
postfix /sbin/nologin
[root@hbs ~]#
#打印第一个和第7个字段 ,但是每个字段都需要站位20个字符串
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%20s %20s\n",$1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
……
dbus /sbin/nologin
polkitd /sbin/nologin
sshd /sbin/nologin
postfix /sbin/nologin
[root@hbs ~]#
# 这里发现右边对的是齐的,用+ - 号对齐,默认是左对齐
# 左对齐的方式打印
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%-20s %-20s\n",$1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
……
sshd /sbin/nologin
postfix /sbin/nologin
[root@hbs ~]#
格式举例:
1、以字符串格式打印 /etc/passwd 的第7 个字段,一冒号 最为分隔符
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s",$7}' /etc/passwd
/bin/bash/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/bin/sync/sbin/shutdown/sbin/halt/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin[root@hbs ~]#
# 加上回车换行
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s\n",$7}' /etc/passwd
/bin/bash
/sbin/nologin
……
/sbin/nologin
/sbin/nologin
[root@hbs ~]#
# 多个换行
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s\n\n\n",$7}' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
……
/sbin/nologin
[root@hbs ~]#
2、以十进制格式打印 /etc/passwd 第三个字段,一冒号作为分隔符
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%d\n",$3}' /etc/passwd
0
1
2
3
……
81
999
74
89
[root@hbs ~]#
常用就这2个,其它了解即可
awk 匹配的两种用法
- 回归工作模式:
读取文本中的一行行数据,首先依据我们的pattern(匹配模式)匹配,如果匹配有就处理,没有就不处理,继续第二行匹配,有就处理,没有就不匹配,继续下一行,一直到匹配完所有文本
1 、 正则表达式
2、关系运算的匹配
正则匹配
匹配/etc/passwd 文件中含有root字符串的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}/root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@hbs ~]#
匹配/etc/passwd 文件中含有ftp 开头的所有行
[root@hbs ~]# awk 'BEGIN{FS=":"}/^ftp/{print $0}' /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@hbs ~]#
关系运算符匹配
运算符 | 含义 |
---|---|
< | 小于 |
> | 大于 |
<= | 小于等于 |
>= | 大于等于 |
== | 等于 |
!= | 不等于 |
~ | 匹配正则表达式 |
!~ | 不匹配正则表达式 |
以冒号为分割符,匹配/etc/passwd 文件中第三个字小安与50的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$3<50{print $3}' /etc/passwd
0
1
2
……
11
12
14
[root@hbs ~]#
以冒号为分割符,匹配/etc/passwd 文件中第三个字段大与50的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$3>50{print $3}' /etc/passwd
99
192
81
999
74
89
[root@hbs ~]#
以冒号为分割符,匹配/etc/passwd 文件中第7个字段为/bin/bash 的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@hbs ~]#
以 冒号分割符 ,匹配/etc/passwd 中第三个 字符串 包含3个以上数字的所有行信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$3~/[0-9](3,)/{print $3}' /etc/passwd
[root@hbs ~]#
布尔运算符
|| 或者
&& 与
! 非
以冒号为分隔符 , 匹配/etc/passwd 文件中 包含ftp 或wyh 的所有行信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$1=="ftp"||$1=="wyh"{print $0}' /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@hbs ~]#
以冒号分割符,匹配 /etc/passwd 文件中第三个字段小于50 并且第4个字段大于50的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$3<=50 && $4 >= 50 {print $0}' /etc/passwd
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@hbs ~]#
awk 动作中的表达式用法
运算符 | 含义 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
^或者** | 乘方 |
++X | 在返回x变量前,x变量+1 (加在前,先+) |
X++ | 在返回后,x变量+1 |
[root@hbs ~]# awk 'BEGIN{var=20;var1="hello";print var,var1}'
20 hello
[root@hbs ~]#
# num1 没有定义 ,默认为0
[root@hbs ~]# awk 'BEGIN{num1=20;num2+=num1;print num1,num2}'
20 20
[root@hbs ~]#
# num 2 除以 num 1
[root@hbs ~]# awk 'BEGIN{num1=20;num2=100;print num2/num1}'
5
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{num1=20;num2=30;printf "%f\n",num1/num2}'
0.666667
[root@hbs ~]#
awk 动作中的条件及循环语句
- 条件语句
if(条件表达式)
动作1
else if(条件表达式)
动作2
else
动作3
以冒号 分割符 ,值打印 /etc/passwd 中第3个字段的数值在50~100 范围内的信息
[root@hbs ~]# awk 'BEGIN{FS=":"}{if($3>50 && $3<100) print $0}' /etc/passwd
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
[root@hbs ~]#
等价于这样:
[root@hbs ~]# awk 'BEGIN{FS=":"}$3 >=50 && $3 <=100{print $0}' /etc/passwd
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{FS=":"}{if($3<50) printf "%s%d","小于50的uid",$3}' /etc/passwd
小于50的uid0小于50的uid1小于50的uid2小于50的uid3小于50的uid4小于50的uid5小于50的uid6小于50的uid7小于50的uid8小于50的uid11小于50的uid12小于50的uid14[root@hbs ~]#
# 没加 \n 换行的效果
[root@hbs ~]# awk 'BEGIN{FS=":"}{if($3<50) printf "%s%d\n","小于50的uid",$3}' /etc/passwd
小于50的uid0
小于50的uid1
小于50的uid2
小于50的uid3
小于50的uid4
小于50的uid5
小于50的uid6
小于50的uid7
小于50的uid8
小于50的uid11
小于50的uid12
小于50的uid14
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{FS=":"}{if($3<50) printf "%-10s %-5d\n","小于50的uid",$3}' /etc/passwd
小于50的uid 0
小于50的uid 1
小于50的uid 2
小于50的uid 3
小于50的uid 4
小于50的uid 5
小于50的uid 6
小于50的uid 7
小于50的uid 8
小于50的uid 11
小于50的uid 12
小于50的uid 14
- 循环语句 do while
do while
do
动作
while (条件表达式)
- for循环
for
for (初始化计数器;计数器测试;计数器变更)
动作
计算1+2+3+4+5+……+100的和,请使用while、do while、for 三种循环方式实现
while 循环
[root@hbs ~]# cat while.sh
BEGIN {
while (i<=100)
{
sum+=i
i++
}
print sum
}
[root@hbs ~]# awk -f while.sh # -f引用
5050
[root@hbs ~]#
for 循环
[root@hbs ~]# cat for.sh
BEGIN{
for(i=0;i<=100;i++)
{
sum+=i
}
print sum
}
[root@hbs ~]# awk -f for.sh
5050
[root@hbs ~]#
do while
[root@hbs ~]# cat do_while.sh
BEGIN{
do
{
sum+=i
i++
}
while (i<=100)
print sum
}
[root@hbs ~]# awk -f do_while.sh
5050
[root@hbs ~]#
awk 选项总结
选项 | 含义 |
---|---|
-v | 参数传递 |
-f | 指定脚本文件 |
-F | 之地那个分割符 |
-V | 查看awk的版本号 |
-v 定义或引用变量
[root@hbs ~]# awk -v num2="$num1" -v var1="$var" 'BEGIN{print num2,var1}'
20 hello
[root@hbs ~]#
-f 指定awk 命令文件
[root@hbs ~]# cat do_while.sh
BEGIN{
do
{
sum+=i
i++
}
while (i<=100)
print sum
}
[root@hbs ~]# awk -f do_while.sh
5050
[root@hbs ~]#
-F 指定分割符
[root@hbs ~]# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd
root
bin
……
sshd
postfix
[root@hbs ~]#
[root@hbs ~]# awk -F ":" '{print $1}' /etc/passwd
root
bin
daemon
……
sshd
postfix
[root@hbs ~]#
-V 查看awk 版本号
[root@hbs ~]# awk -V
GNU Awk 4.0.2
Copyright (C) 1989, 1991-2012 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
[root@hbs ~]#
- 关于awk 的用法,其实还有很多,包括后面的awk数组中用法等等,如果感兴趣的话,您可以留言,大家一起研究awk编程的内容