目录
一、正则表达式
1、正则表达式的概述
1.1 正则表达式的概念和作用
1.2 正则表达式支持的语言
1.3 正则表达式的优缺点
1.4 正则表达式的分类
1.4.1 基本正则表达式(BRE):
1.4.2 扩展正则表达式(ERE):
1.4.3 区别
1.5 帮助命令
2、基础正则表达式
2.1 字符匹配
2.1.1 元字符点
2.1.2 字符组
2.2 匹配次数
2.3 位置锚定
2.4 分组或其他
2.4.1 分组
2.4.2 或者
2.4.3 非打印字符
3、扩展正则表达式
3.2 字符匹配
3.2 匹配次数
3.3 位置锚定
2.4 分组或其他
二、文本处理三剑客之grep
1、grep用法
2、grep案例
2.1 匹配qq号
2.2 匹配邮箱
2.3 匹配手机号
2.4 查询 /etc/passwd 文件中有 root 的行
2.5 将非#开头和非空白行的文本写入到其他文本
2.6 匹配行首和行尾单词相同的行
2.7 多个模式条件匹配
2.8 提取出字符串中的所有数字
2.9 统计文件单词个数
三、文本处理三剑客之sed
1、sed概述
1.1 sed概念
1.2 sed工作原理
1.3 sed优缺点
2、sed基本用法
3、sed搜索替换
4、sed分组查找替换
5、sed变量查找
6、使用sed工具修改配置文件
6.1 直接修改httpd的80端口
6.2 修改网卡名
7、sed高级用法(了解)
四、文本处理三剑客之awk
1、awk的概述
2、awk基本用法
2.1 awk基本格式和执行流程
2.2 基本打印用法(动作 print)
2.3 常见的内置变量
2.5 模式PATTERN
2.6 awk结合数组运用
2.7 条件判断(if)
2.8 循环(for、while)
2.9 awk脚本(了解)
五、案例
1、统计当前主机的连接状态
2、统计当前连接主机数
3、过滤主机ip地址
4、 提取13:01到14:02之间的日志
5、提取下图ip地址及时间
6、提取host.txt主机名再放回host.txt文件
7、提取以数字形式显示/etc/passwd的权限
8、 统计/etc/fstab文件中每个文件系统类型出现的次数
REGEXP(Regular Expressions)由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能,但与通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容
可用于匹配、搜索和替换文本。通过使用一系列的字符和元字符,以及特定的语法规则,正则表达式可以帮助你找到符合特定模式的文本
vim, less,grep,sed,awk, nginx,mysql
优点:
缺点:
元字符的区别:
\( \)
代表分组,\{ \}
代表重复次数,而|
或+
等特殊字符需要使用反斜杠转义()
代表分组,{}
代表重复次数,|
或+
等特殊字符不需要转义重复操作符的区别:
+
和?
等重复操作符不具备特殊含义,需要使用反斜杠转义来表示它们的特殊含+
和?
等重复操作符可以直接使用,具有特殊含义#可以使用 man 手册帮助
man 7 regex
元字符
预订好且具有特殊含义的符号,这些符号能够进行通配
. 匹配任意单个字符,可以是一个汉字
r[.]t 在[ ]内的 . 代表原来的意思
[ ] 匹配指定范围内的任意单个字符
如:[0-9] 只匹配0~9范围内的任意单个数字
[0-59] 表示匹配0~5和9而不是0~59
[a-z] 只匹配a~z范围内的任意单个小写字母
[a-zA-Z] 只匹配a~z或A~Z范围内的任意单个字母
[^] 匹配指定范围外的任意单个字符,即取反。
注意 ^ 在括号内,在括号外代表行首,如:[^abcd] 匹配除a b c d外的其他所有字符
[[:alnum:]]= [0-9a-zA-Z] 匹配字母和数字
[[:alpha:]]= [a-zA-Z] 代表任何英文大小写字符
[[:lower:]]=[a-z] 小写字母
[[:upper:]]=[A-Z] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:] 十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 匹配所有标点符号, ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` {
[:graph:] 图形字符,即能展现字符颜色的符号,等价于 [:alnum:] + [:punct:]
特殊元字符在中括号中的匹配:
想要在中括号中匹配 ^ ,需将其放在中括号的非开头位置,如[a^]
想要在中括号中匹配 - ,需将其放在开头位置或结尾位置,如[abc-] [-abc]
想要在中括号中匹配 ] ,需将其放在开头位置或结尾位置,如[abc]] []abc]
想要匹配上面2个或三个元字符,如[]^] [-^] []-] []^-]
* 匹配前面的字符任意次,包括 0 次
.* 任意长度的任意字符
\? 匹配其前面的字符 0 或 1 次,即:可有可无
\+ 匹配其前面的字符至少 1 次,即:>=1
\{n\} 匹配前面的字符 n 次
\{m,n\} 匹配前面的字符至少 m 次,至多 n 次
\{,n\} 匹配前面的字符至多 n 次,<=n
\{n,\} 匹配前面的字符至少 n 次
位置锚定可以用于定位出现的位置
^ 行首锚定,用于模式的最左侧
$ 行尾锚定,用于模式的最右侧
^$ 空行
^[[:space:]]*$ 空行或包含空白字符的行
^PATTERN$ 用于模式匹配整行
\< 或 \b 匹配单词边界,表示锚定词首,其后面的字符必须作为单词首部出现
\> 或 \b 匹配单词边界,表示锚定词尾,其前面的字符必须作为单词尾部出现
\ 匹配整个单词
() 将多个字符捆绑在一起,当作一个整体处理,如:\(root\)+
a\|b # a 或 b
C\|cat # C 或 cat
\(C\|c\)at # Cat 或 cat
\n 匹配换行符
\r 匹配回车符
\t 匹配制表符
\w 匹配单词字符,相当于[a-zA-Z0-9_]
单词字符包括字母、数字和下划线
\W 匹配非单词字符,相当于[^a-zA-Z0-9_]
\s 匹配空白字符
\S 匹配非空白字符
\d 匹配数字
\D 匹配非数字
扩展正则表达式的元字符用法与基础正则表达式的元字符用法相差不大,区别在于扩展正则表达式不需要使用转义符,而基础正则表达式需要使用转义符
. 匹配任意单个字符,可以是一个汉字
r[.]t 在[ ]内的 . 代表原来的意思 点
[ ] 匹配指定范围内的任意单个字符
如:[0-9] 只匹配0~9范围内的任意单个数字
[0-59] 表示匹配0~5和9而不是0~59
[a-z] 只匹配a~z范围内的任意单个小写字母
[a-zA-Z] 只匹配a~z或A~Z范围内的任意单个字母
[^] 匹配指定范围外的任意单个字符,即取反。
注意 ^ 在括号内,在括号外代表行首,如:[^abcd] 匹配除a b c d外的其他所有字符
[[:alnum:]]= [0-9a-zA-Z] 匹配字母和数字
[[:alpha:]]= [a-zA-Z] 代表任何英文大小写字符
[[:lower:]]=[a-z] 小写字母
[[:upper:]]=[A-Z] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
[:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
[:digit:] 十进制数字
[:xdigit:] 十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 匹配所有标点符号, ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` {
[:graph:] 图形字符,即能展现字符颜色的符号,等价于 [:alnum:] + [:punct:]
* 匹配前面的字符任意次,包括 0 次
.* 任意长度的任意字符
? 匹配其前面的字符 0 或 1 次,即:可有可无
+ 匹配其前面的字符至少 1 次,即:>=1
{n} 匹配前面的字符 n 次
{m,n} 匹配前面的字符至少 m 次,至多 n 次
{,n} 匹配前面的字符至多 n 次,<=n
{n,} 匹配前面的字符至少 n 次
^ 行首锚定,用于模式的最左侧
$ 行尾锚定,用于模式的最右侧
^$ 空行
^[[:space:]]*$ 空行或包含空白字符的行
^PATTERN$ 用于模式匹配整行
\< 或 \b 匹配单词边界,表示锚定词首,其后面的字符必须作为单词首部出现
\> 或 \b 匹配单词边界,表示锚定词尾,其前面的字符必须作为单词尾部出现
\ 匹配整个单词
() 分组
| 或者
a|b # a 或 b
C|cat # C 或 cat
(C|c)at # Cat 或 cat
\n 匹配换行符
\r 匹配回车符
\t 匹配制表符
\w 匹配单词字符,相当于[a-zA-Z0-9_]
单词字符包括字母、数字和下划线
\W 匹配非单词字符,相当于[^a-zA-Z0-9_]
\s 匹配空白字符
\S 匹配非空白字符
\d 匹配数字
\D 匹配非数字
grep
是一个强大的文本搜索工具,它可以在文件中查找特定模式的文本,并将包含这些模式的行进行筛选
grep [选项]…… 查找条件 源文件
-m 匹配指定次数后停止
-v 显示不被模式匹配到的行,取反
-i 忽略字符大小写
-n 显示行号
-c 统计匹配的行数
-o 仅显示匹配到的字符串
-q 静默模式,不输出任何信息
-e 实现多个选项间的逻辑 or 关系,如:grep -e "yellow" -e "red" file
-w 匹配整个单词
-E 使用扩展正则表达式,相当于 egrep
-F 不支持正则表达式,相当于 fgrep
-r 递归目录,但不处理软链接
-R 递归目录,但处理软链接
-f file 根据模式文件处理
-A n after, 后 n 行
-B n before, 前 n 行
-C n context, 前后各 n 行
[root@localhost ~]#grep -Eo "\b[0-9]{6,12}\b" 1.txt
[root@localhost ~]#grep -Eo "[0-9a-zA-Z_]+@[0-9a-zA-Z_]+\.[0-9a-zA-Z_]+" 1.txt
[root@localhost ~]#grep -Eo "[[:alnum:]_-]+@[[:alnum:]_]+\.[[:alnum:]_]+" 1.txt
[root@localhost ~]#grep -Eo "\b1[3456789][0-9]{9}\b" 1.txt
[root@localhost ~]#grep "root" /etc/passwd
[root@localhost ~]#grep -Ev "^(#|$)" /etc/profile > 1.txt
[root@localhost ~]#grep "^\(.*\)\>.*\<\1$" /etc/passwd
[root@localhost ~]#grep -Eo "^(.*)\>.*\<\1$" /etc/passwd
#多个匹配条件之间的关系为或者
[root@localhost ~]#grep -e "root" -e "/bin/bash" /etc/passwd
[root@localhost ~]#echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|grep -o [0-9]
[root@localhost data]#cat /etc/fstab |grep -Eo "\b[[:alpha:]]+\b"|wc -l
[root@localhost data]#cat /etc/fstab |grep -Eo "\b[[a-zA-Z]]+\b"|wc -l
sed
是一个流式文本编辑器,用于对文本进行替换、删除、插入等操作优点
sed
提供了丰富的文本处理命令和正则表达式支持,可以完成各种复杂的文本操作,如查找、替换、删除、插入等。它的功能强大且灵活,能够满足众多文本处理需求sed
是基于流处理的工具,逐行读取和处理文本,因此在处理大型文件时非常高效,不会占用过多的内存和系统资源。这使得它适用于处理大量文本数据sed
可以通过简单的命令一次性对多行文本进行处理,因此非常适合批量处理文本数据。它可以轻松地应用于一组文件或整个目录中的文件sed
是一个跨平台的工具,可在不同的操作系统上(如Linux、UNIX、macOS等)使用。这使得它在各种环境中都能发挥作用,具有广泛的适用性。缺点
sed
的命令语法相对较复杂,特别是对于初学者来说可能会有一定的学习曲线。对于一些复杂的处理任务,也可能需要深入了解正则表达式和高级命令才能灵活应用sed
是基于行的文本处理工具,因此无法直接处理多行文本。它只能处理当前行,对于需要跨行操作的任务,可能会显得不够方便sed
默认情况下会直接修改文件内容,而不是将处理结果输出到标准输出。这意味着如果不小心操作,可能会不可逆地修改原始数据。因此,在使用 -i
选项时应格外小心sed
是一条命令行工具,通常在批处理环境下使用,并不支持与用户进行实时交互。这对于需要实时响应用户输入或交互的任务可能会有所不便(1)格式
sed [option]... 'script;script;...' [input file...]
sed [选项] '自身脚本命令语法' 支持标准输入的文件
自身脚本命令语法=地址+脚本操作命令
(2)选项
常用选项 | 说明 |
---|---|
-n | 不输出模式空间内容到屏幕,即不自动打印 |
-e | 多点编辑,如sed -n -e '/^r/p' -e'/^b/p' /etc/passwd 输出以r和以b开头的文本行 |
-f FILE | 从指定文件中读取编辑脚本 |
-r, -E | 使用扩展正则表达式 |
-i.bak | 备份源文件为以".bak“结尾的文件(文件后缀名可随意),并源文件处继续编辑 |
(3)自身脚本命令语法
自身脚本命令语法=地址+脚本操作命令
①地址
地址 | 说明 | |
---|---|---|
无地址 | 空格 | 对全文进行处理,如sed ' ' /etc/fstab=cat /etc/fstab 查看文件内容 |
单地址 | #(数字) | 指定的行,如sed -n '2p' /etc/passwd 只打印指定的第二行 |
$ | 最后一行,如sed -n '$p' /etc/passwd 只删除打印的最后一行(对源文件无影响) |
|
/pattern/ | 被此处模式所能够匹配到的每一行,正则表达式 | |
地址范围 | m,n | 从第 m 行到第 n 行 sed -n '1,3p' /etc/passwd 只打印文件内容的第1到第3行 |
m,+n | 从第 m 行到第 m+n 行 sed -n '1,+4p' /etc/passwd 只打印文件内容的第1到第5行 |
|
/pat1/,/pat2/ | 第一个正则表达式和第二个正则表达式之间的行 如sed -n '/^r/,/^f/p' /etc/passwd 打印以r开头的行到以f开头的行中间的所有行 |
|
#,/pat/ | 从#行为开始找到 pat为止 如sed -n '3,/^f/p' /etc/passwd 打印第三行到以b开头的行中间的所有行 |
|
/pat/,# | 找到#号个pat为止 如sed -n '/^r/,3' /etc/passwd 打印以r开头的行到第三行中间的所有行 |
|
步进 | 1~2 | 奇数行, 第一个数为起始行后一个数字为前进步数 cat -n /etc/passwd | sed -n "1~2p" 只打印文件里的奇数行内容 |
2~2 | 偶数行, 第一个数为起始行后一个数字为前进步数 cat -n /etc/passwd | sed -n "2~2p" 只打印文件里的偶数行内容 |
②脚本操作命令
脚本操作命令 | 说明 |
---|---|
a | 增加,在当前行下面增加一行指定内容,支持使用 \n 实现多行追加 |
i | 插入,在选定行上面插入一行指定内容 |
c | 替换,将选定行替换为指定内容 |
d | 删除,删除选定的行 |
w file | 保存模式匹配的行至指定文件 |
r file | 读取指定文件的文本至模式空间中匹配到的行后 |
p | 打印当前模式空间内容,追加到默认输出之后。 如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容 |
Ip | 忽略大小写输出 |
! | 模式空间中匹配行取反处理 |
= | 为模式空间中的行打印行号 |
注:
以上的操作其实是对输出内容的修改,其实对源文件本身没有影响,如果想修改源文件,需启用 -i 选项
脚本操作命令 | 说明 |
---|---|
s | 替换,替换指定字符,格式 s/文件旧内容/替换的内容/修饰符 |
y | y字符转换,和 s 用法类似,但只能替换大小写 |
g | 行内全局替换 |
p | 显示替换成功的行 |
I或者i | 忽略大小写 |
w file | 将替换成功的行保存至文件中 |
[root@localhost ~]#sed 's/root/admin/g' /etc/passwd
[root@localhost ~]#sed 's/r..t/&er/g' /etc/passwd
[root@localhost ~]#echo 123xyzabc |sed -r 's/123(xyz)abc/\1/'
[root@localhost ~]#echo 123xyzabc |sed -r 's/(123)(xyz)(abc)/\1\2/'
[root@localhost ~]#echo 123xyzabc |sed -r 's/(123)(xyz)(abc)/\3\2\1/'
#先定义变量再用sed命令调用该变量值
root@localhost ~]#name=root
[root@localhost ~]#sed -nr "/$name/p" /etc/passwd
[root@localhost ~]#sed -nr '/'$name'/p' /etc/passwd #两单引号也可以查询
sed可以用于修改配置文件,它可以从标准输入或文件中读取文本,并对其进行编辑和转换
[root@localhost ~]#grep "Listen" /etc/httpd/conf/httpd.conf
[root@localhost ~]#port=8080
[root@localhost ~]#sed -ri 's/^Listen 80/Listen '$port'/' /etc/httpd/conf/httpd.conf
[root@localhost ~]#cat /etc/default/grub
[root@localhost ~]#sed -ri.bak '/^GRUB_CMDLINE_LINUX/s#(.*)"#\1 net.ifnames=0"#' /etc/default/grub
#使用分组替换,(.*)指得是 “号前面的所有,即在“号前,quiet后添加 net.ifnames=0(注意空格)
[root@localhost ~]#grep GRUB_CMDLINE_LINUX /etc/default/grub
#其他方法
[root@localhost ~]#sed -ri.bak '/^GRUB_CMDLINE_LINUX/s#"$#net.ifnames=0"#' /etc/default/grub
#直接将"号替换成"$#net.ifnames=0"
#修改完配置文件,注意重新生成grub配置文件
[root@localhost ~]#grub2-mkconfig -o /boot/grub2/grub.cfg
sed 中除了模式空间之外还支持保持空间(Hold Space),利用此空间,可以将模式空间中的数据临时保存至保持空间,从而后续接着处理,实现更为丰富的功能
P 打印模式空间开端至 \n 内容,并追加到默认输出之前
h 把模式空间中的内容覆盖至保持空间中
H 把模式空间中的内容追加至保持空间中
g 从保持空间取出数据覆盖至模式空间
G 从保持空间取出内容追加至模式空间
x 把模式空间中的内容与保持空间中的内容进行互换
n 读取匹配到的行的下一行覆盖至模式空间
N 读取匹配到的行的下一行追加至模式空间
d 删除模式空间中的行,也可以叫剪切
D 如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出 d 命令那样启动正常的新循环
[root@localhost ~]#sed -n 'N;p' #奇数行
[root@localhost ~]#sed -n 'n;p' #偶数行
[root@localhost ~]#sed -n 'n;P' #偶数行
#将第一行和第二行合并成一行并指定分隔符
[root@localhost ~]#seq 10 | sed 'N;s/\n//'
[root@localhost ~]#seq 10 | sed 'N;s/\n/:/'
[root@localhost ~]#sed -n '1!G;h;$!d' #倒序
awk是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令。 用于从文件、管道或标准输入中读取文本,并根据用户指定的模式和操作进行处理
awk
提取文件中的特定字段或行,并对其进行转换和格式化。awk
对结构化数据进行分析,并生成报告、统计信息或汇总数据。awk
对文本进行格式化、排序、过滤和合并等操作。awk
脚本来实现特定的文本处理逻辑,满足特定的需求awk [options] 'program' var=value file…
选项 语法 值 文件,支持标准输入、输出
awk 'pattern { action }' input_file
注:
语法program通常是被放在单引号中,可分为pattern和action:
pattern:用于匹配输入文本的模式。可以使用正则表达式或字符串进行匹配。如果省略模式,则默认匹配所有行
action:对数据进行处理的操作,放在{}内指明,在满足模式的情况下要执行的动作。可以是单个命令或多个命令组合。如果省略动作,则默认打印整行。处理动作常见print、printf①一定是单引号: '模式或条件{操作}'
② {}外指定条件,{}内指定操作
③ 内建变量不能使用双引号括起来,不然系统会把它当成字符串
执行流程:
① 执行BEGIN{action;… }{print}语句块中的语句
② 从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,
从第一行到最后一行重复这个过程,直到文件全部被读取完毕
③ 当读至输入流末尾时,执行END{action;…}语句块
BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
常用选项 | 说明 |
---|---|
-F "分隔符" | 指明输入时用到的字段分隔符 |
-f | 指定调用脚本 |
-v var=value | 变量赋值 |
print item1,item2, ...
逗号做分隔符,用 {} 包起来
输出的 item 可以是字符串,也可是数值,当前记录的字段、变量或 awk 的表达式
如省略 item,相当于 print $0
[root@localhost ~]#awk '' #program为空,没有效果
[root@localhost ~]#awk '{print}' /etc/passwd #输出/etc/passwd文件所有内容
相当于cat /etc/passwd 和sed ' ' /etc/passwd
[root@localhost ~]#awk -F: '{print $1,$7}' /etc/passwd
[root@localhost ~]#awk -F: '{print $1":"$7}' /etc/passwd
[root@localhost ~]#awk -F: '{print $1","$7}' /etc/passwd
内置变量 | 说明 |
---|---|
NR | 当前处理的行的行号(序数) |
NF | 当前处理的行的字段个数 |
FS | 指定每行文本的字段分隔符,默认为空格或制表位 与 “ -F ” 作用相同 |
OFS | 输出内容的列分隔符 |
RS | 行分隔符,awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。预设值是"\n" |
$0 | 当前处理的行的整行内容 |
$n | 当前处理行的第n个字段(第n列) |
FILENAME | 被处理的文件名 |
(1)NR:行号
当前处理的行的行号(序数)
[root@localhost ~]#awk -F: '{print $1,NR}' /etc/passwd
[root@localhost ~]#awk -F: '{print NR,$1}' /etc/passwd
[root@localhost ~]#awk 'NR==2{print $1}' /etc/passwd
[root@localhost ~]#awk 'NR==1,NR==3{print}' /etc/passwd
[root@localhost ~]#awk 'NR==1||NR==3{print}' /etc/passwd
[root@localhost ~]#awk 'NR>=3 && NR<=6{print NR,$0}' /etc/passwd
[root@localhost ~]#seq 10|awk 'NR>5 && NR<10'
#如何打印普通用户及其uid
[root@localhost ~]#awk -F: '$3>1000{print $3,$1}' /etc/passwd|sort -n
(2)NF
当前处理的行的字段个数
[root@localhost ~]#awk -F: '{print NF}' /etc/passwd
[root@localhost ~]#awk -F: '{print $NF}' /etc/passwd
[root@localhost ~]#awk -F: '{print $(NF-2)}' /etc/passwd
(3)FS
指定每行文本的字段分隔符,默认为空格或制表位,与 “ -F ” 作用相同
[root@localhost ~]#awk -F: '{print $1":"$3}' /etc/passwd
[root@localhost ~]#awk -v FS=':' '{print $1FS$3}' /etc/passwd
(4)OFS
输出内容的列分隔符
[root@localhost ~]#awk -v FS=':' -v OFS='==' '{print $1,$3}' /etc/passwd
(5)RS
行分隔符,awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。预设值是"\n"
[root@localhost ~]#echo $PATH | awk -v RS=":" '{print $1}'
(6)$0
当前处理的行的整行内容
[root@localhost ~]#awk -F: '{print $0}' /etc/passwd
(7) FILENAME
显示处理的文件名
[root@localhost ~]#awk -F: 'NR==2{print FILENAME}' /etc/passwd
(1)模式为空
如果模式为空表示每一行都匹配成功,相当于没有额外条件
如:awk -F: '{print $1,$3}' /etc/passwd
(2)正则匹配
/regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
[root@localhost ~]#ifconfig ens33|awk '/netmask/{print}'
[root@localhost ~]#awk '/^root/{print}' /etc/passwd
(3)line ranges:行范围
不支持使用行号,但是可以使用变量NR间接指定行号加上比较操作符或者逻辑关系
算术操作符
x+y, x-y, x*y, x/y, x^y, x%y
-x:转换为负数
+x:将字符串转换为数值
比较操作符:
==, !=, >, >=, <, <=
逻辑操作符
与:&&,并且关系
或:||,或者关系
非:!,取反
模式匹配符:
~ 左边是否和右边匹配,包含关系
!~ 是否不匹配
$n (><==) | 用于对比数值 |
$n~"字符串" | 代表第n个字段,包含某个字符串的作用 |
$n!~"字符串" | 代表第n个字段,不好含某个字符串的作用 |
$n=="字符串" | 代表第n个字段为某个字符串的作用 |
$n!="字符串" | 代表第n个字段不为某个字符串的作用 |
$NF | 代表最后一个字段 |
#输出第七个字段包含“bash”所在行的第一个字段和最后一个字段
[root@localhost ~]#awk -F: '$7~"bash"{print $1,$NF}' /etc/passwd
#输出第七个字段不包含“nologin”所在行的第一个字段和最后一个字段
[root@localhost ~]#awk -F: '$7!~"nologin"{print $1,$NF}' /etc/passwd
#指定第六个字段为/home/dh,第七个字段为/bin/bash,输出满足这些条件的所在行
[root@localhost ~]#awk -F: '($6=="/home/dh")&&($7=="/bin/bash"){print $0}' /etc/passwd
(4)/pat1/,/pat2/
pat代表正则表达式,pat1到pat2 表示从正则表达式1到正则表达式2
#打印以r开头的行到以b开头的行中间的所有行
[root@localhost ~]#awk '/^r/,/^f/' /etc/passwd
(5)关系表达式
在awk中,关系表达式用于比较两个值,并返回一个布尔值(真或假)。这些表达式通常用于控制流程和过滤数据,关系表达式结果为“真”才会被处理。
真:结果为非0值,非空字符串
假:结果为空字符串或0
[root@localhost ~]#echo 123 | awk '1{print}' #1 允许打印
[root@localhost ~]#echo 123 | awk '0{print}' #0 不允许打印
[root@localhost ~]# seq 5 | awk 'n++'
[root@localhost ~]# seq 5 | awk '!n++'
[root@localhost ~]# seq 5 | awk '!0' #全部打印
[root@localhost ~]# seq 5 | awk 'i=!i' #打印奇数行
[root@localhost ~]# seq 5 | awk '!(i=!i)' #打印偶数行
(6) BEGIN END
BEGIN{}:仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次
[root@localhost ~]#awk -F: 'BEGIN {print "USERID USER"} {print $3,$1}' /etc/passwd
[root@localhost ~]#awk -F: '{print $3,$1} END{print "USERID USER"}' /etc/passwd
[root@localhost ~]#awk -F: 'BEGIN {print "USERID USER"} {print $3","$1} END{print "END FILE"}' /etc/passwd
#支持运算
[root@localhost ~]#awk 'BEGIN {print 2*2}'
[root@localhost ~]#awk 'BEGIN {print 6/2}'
[root@localhost ~]#awk 'BEGIN {print 6+2}'
在awk中,数组是一种非常有用的数据结构,用于存储和操作数据。awk中的数组是关联数组,也就是说它们可以使用字符串作为索引。
awk数组特性:
①awk的数组是关联数组(即key/value方式的hash数据结构),索引下标可为数值(甚至是负数、小数等),也可为字符串
②awk数组支持数组的数组
(1)awk中定义数组打印
可以使用数组的索引来访问和修改数组元素的值
[root@localhost ~]#awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[0]}'
[root@localhost ~]#awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[2]}'
(2)数组长度
awk提供了 length() 函数来获取数组的元素个数,它也可以用于获取字符串的字符数量。还可以获取数值转换成字符串后的字符数量
[root@localhost ~]#awk 'BEGIN{name["a"]="lcc";name["b"]="xz";name["c"]="dh";for(i in name)print name[i];print length(name)}'
(3)遍历数组
使用for循环来迭代数组中的元素
for(var in array) {for-body}
awk 'BEGIN{name["a"]="zhangsan";name["b"]="lisi";name["c"]="wangwu";for(i in name)print name[i]}'
(4)awk打印文件内容去重统计
①去重打印数组
[root@localhost ~]#x=(10 10 10 20 30 20 30 20 40 10 30 10)
[root@localhost ~]#echo ${x[@]}|awk -v RS=' ' '!a[$1]++'
②处理文件去重统计
原理:将文件的字段内容变为定义的数组下标,对其进行匹配读取累加(只有遇到完全一致的才会累加),此时重复的次数在for循环的作用下成为了数组对应下标的元素,所以输出该下标和元素(就等同于输出重复的字段内容 以及统计的重复次数)
[root@localhost ~]#cat 1.txt
[root@localhost ~]#awk '!a[$0]++' 1.txt
[root@localhost ~]#cat 1.txt
[root@localhost ~]#awk '{a[$1]++};END{for(i in a){print i,a[i]}}' 1.txt
在awk中,条件判断通常用于控制程序的流程,以便根据特定条件执行不同的操作。条件判断通常与if语句结合使用
awk 选项 '模式 {actions}'
#条件判断写在 actions里
if语句:awk的if语句也分为单分支、双分支和多分支
单分支为if(判断条件){执行语句}
双分支为if(判断条件){执行语句}else{执行语句}
多分支为if(判断条件){执行语句}else if(判断条件){执行语句}else if(判断条件){执行语句}else if(判断条件){执行语句}
[root@localhost ~]# awk -F: '{if($3>=1000){print $3,$1}else{print $1}}' /etc/passwd
在awk中,可以使用循环语句来重复执行一组操作,直到满足特定条件为止。awk支持for循环和while循环
awk 选项 '模式 {actions}'
#循环语句写在 actions里
#condition为条件;statement为语句
for(expr1;expr2;expr3) {statement;…}
for(variable assignment;condition;iteration process) {for-body}
for(var in array) {for-body}
#计算1+2+3……+99+100的总和
[root@localhost ~]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
#!/bin/awk -f
{if($3>=1000){print $3,$1}}
[root@localhost ~]#ss -nta | grep -v '^State' |cut -d" " -f1|sort |uniq -c
[root@localhost ~]#ss -nta|awk 'NR!=1{State[$1]++};END{for(i in State){print State[i],i}}'
[root@localhost ~]#ss -nat|awk 'NR!=1{print $1}' | sort |uniq -c
[root@localhost ~]#ss -nt |tail -n +2|tr -s " "|cut -d " " -f5|cut -d ":" -f1 |sort|uniq -c
[root@localhost ~]#ss -nt|awk -F "[ :]+" 'NR!=1{print $6}'|sort|uniq -c
[root@localhost ~]#ss -nt|awk "-F[ :]+" 'NR!=1{a[$6]++};END{for(i in a){print a[i],i}}'
[root@localhost ~]#ifconfig ens33|grep netmask|tr -s " "|cut -d " " -f3
[root@localhost ~]#ifconfig ens33 | sed -rn '2s/.*inet (.*) netmask.*/\1/p'
[root@localhost ~]#ifconfig ens33 | sed -rn '2s/.*inet ([0-9.]+) .*/\1/p'
[root@localhost ~]#ifconfig ens33 | awk '/netmask/{print $2}'
[root@localhost log]#sed -nr '/Jan 31 13:00:01/,/Jan 31 14:00:02/p' /var/log/messages
[root@localhost log]#awk '/Jan 31 13:00:01/,/Jan 31 14:00:02/{print $0}' /var/log/messages
[root@localhost data]#cat log.txt |sed -nr 's/(.*) - - \[(.*) \+.*/\1 \2/p'
[root@localhost data]#cat log.txt |awk -F"[[ ]" '{print $1,$5}'
[root@localhost data]#cat log.txt |awk -F"[[ ]+" '{print $1,$4}'
[root@localhost data]#cat host.txt |awk -F"[ .]+" '{print $2}' >> host.txt
[root@localhost data]#cat host.txt |cut -d "." -f1 |tr -d "[0-9 ]" >> host.txt
[root@localhost data]#cat host.txt |sed -nr 's/.* (.*)\.(.*)\.(.*)/\1/p' >> host.txt
[dh@localhost ~]$stat /etc/passwd|awk -F"[(/]" 'NR==4{print $2}'
[dh@localhost ~]$stat /etc/passwd|sed -nr '4s/.*\(([0-9]{4}).*/\1/p'
[dh@localhost ~]$stat /etc/passwd|grep "权限"|cut -d ")" -f1|cut -d"(" -f2|cut -d"/" -f1
[root@localhost ~]#cat /etc/fstab |awk '/^[^#]/{print $3}'|sort|uniq -c
[root@localhost ~]#grep -Ev "^(#|$)" /etc/fstab|awk '{print $3}'|sort -n|uniq -c
[root@localhost ~]#cat /etc/fstab |awk '/^[^#]/{a[$3]++};END{for(i in a){print a[i],i}}'