正则表达式及文本处理三剑客(grep、sed、awk)

目录

一、正则表达式

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文件中每个文件系统类型出现的次数


一、正则表达式

1、正则表达式的概述

1.1 正则表达式的概念和作用

REGEXP(Regular Expressions)由一类特殊字符及文本字符所编写的模式,其中有些字符(元字符)不表示字符字面意义,而表示控制或通配的功能,类似于增强版的通配符功能,但与通配符不同,通配符功能是用来处理文件名,而正则表达式是处理文本内容

可用于匹配、搜索和替换文本。通过使用一系列的字符和元字符,以及特定的语法规则,正则表达式可以帮助你找到符合特定模式的文本

1.2 正则表达式支持的语言

vim, less,grep,sed,awk, nginx,mysql

1.3 正则表达式的优缺点

优点:

  • 强大的模式匹配能力:正则表达式能够描述复杂的字符串模式,包括匹配特定字符、重复次数、字符集合等,使其可以用于强大的模式匹配和搜索
  • 灵活性:正则表达式可以适应不同的文本模式,可以通过简洁而灵活的语法来描述各种匹配规则
  • 广泛支持:正则表达式在许多编程语言和工具中得到广泛支持,可以在不同平台和环境下使用
  • 文本处理和数据提取:正则表达式广泛用于文本处理、数据提取、文本替换等方面,能够快速、高效地进行字符串操作

缺点:

  • 复杂性:正则表达式的语法相对复杂,有一定的学习曲线,特别是在处理复杂模式时,编写和理解正则表达式可能会有一定的困难
  • 易读性:一些复杂的正则表达式可能难以阅读和理解,特别是对于不熟悉正则表达式的人来说,维护和修改这样的正则表达式可能会有困难
  • 性能:一些复杂的正则表达式可能会导致性能问题,特别是在大型文本上进行匹配时,需要谨慎设计正则表达式以避免性能瓶颈

1.4 正则表达式的分类

1.4.1 基本正则表达式(BRE):
  • 使用元字符时在其前面添加反斜线转义:\? 、 \+ 、 \{ 、 \} 、 \| 、 \( 和 \)
  •  grep sed默认使用基础正则表达式
1.4.2 扩展正则表达式(ERE):
  • 使用元字符时不需要在其前面添加反斜线转义:? 、 + 、 { 、 } 、 | 、 ( 和 )
  • grep -E、sed -r、egrep、awk扩展正则表达式
1.4.3 区别

元字符的区别

  • 基本正则表达式中需要使用反斜杠转义的方式来匹配特殊字符,比如\( \)代表分组,\{ \}代表重复次数,而|+等特殊字符需要使用反斜杠转义
  • 扩展正则表达式中通常不需要使用反斜杠转义来匹配特殊字符,比如()代表分组,{}代表重复次数,|+等特殊字符不需要转义

重复操作符的区别

  • 基本正则表达式+?等重复操作符不具备特殊含义,需要使用反斜杠转义来表示它们的特殊含
  • 扩展正则表达式+?等重复操作符可以直接使用,具有特殊含义

1.5 帮助命令

#可以使用 man 手册帮助
man 7 regex

 2、基础正则表达式

元字符

预订好且具有特殊含义的符号,这些符号能够进行通配

2.1 字符匹配

2.1.1 元字符点
.   	匹配任意单个字符,可以是一个汉字

r[.]t     在[ ]内的 . 代表原来的意思

 2.1.2 字符组
[ ]      	匹配指定范围内的任意单个字符
如:[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个或三个元字符,如[]^]  [-^]  []-]  []^-]

2.2 匹配次数

* 		匹配前面的字符任意次,包括 0 次
.* 		任意长度的任意字符
\? 		匹配其前面的字符 0 或 1 次,即:可有可无
\+ 		匹配其前面的字符至少 1 次,即:>=1
\{n\} 	匹配前面的字符 n 次
\{m,n\} 匹配前面的字符至少 m 次,至多 n 次
\{,n\} 	匹配前面的字符至多 n 次,<=n
\{n,\} 	匹配前面的字符至少 n 次

2.3 位置锚定

位置锚定可以用于定位出现的位置

^	行首锚定,用于模式的最左侧
$	行尾锚定,用于模式的最右侧
^$	空行
^[[:space:]]*$	空行或包含空白字符的行
^PATTERN$ 	    用于模式匹配整行
\< 或 \b 	    匹配单词边界,表示锚定词首,其后面的字符必须作为单词首部出现
\> 或 \b        匹配单词边界,表示锚定词尾,其前面的字符必须作为单词尾部出现
\<PATTERN\>     匹配整个单词

 2.4 分组或其他

2.4.1 分组
()    将多个字符捆绑在一起,当作一个整体处理,如:\(root\)+
2.4.2 或者
a\|b	    # a 或 b  
C\|cat	    # C 或 cat  
\(C\|c\)at	# Cat 或 cat
2.4.3 非打印字符
\n	匹配换行符
\r	匹配回车符
\t	匹配制表符
\w  匹配单词字符,相当于[a-zA-Z0-9_]
    单词字符包括字母、数字和下划线
\W  匹配非单词字符,相当于[^a-zA-Z0-9_]
\s  匹配空白字符
\S  匹配非空白字符
\d  匹配数字
\D  匹配非数字

3、扩展正则表达式

扩展正则表达式的元字符用法与基础正则表达式的元字符用法相差不大,区别在于扩展正则表达式不需要使用转义符,而基础正则表达式需要使用转义符

3.2 字符匹配

.   	匹配任意单个字符,可以是一个汉字
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:]

3.2 匹配次数

* 		匹配前面的字符任意次,包括 0 次
.* 		任意长度的任意字符
? 		匹配其前面的字符 0 或 1 次,即:可有可无
+ 		匹配其前面的字符至少 1 次,即:>=1
{n} 	匹配前面的字符 n 次
{m,n}   匹配前面的字符至少 m 次,至多 n 次
{,n} 	匹配前面的字符至多 n 次,<=n
{n,} 	匹配前面的字符至少 n 次

3.3 位置锚定

^	行首锚定,用于模式的最左侧
$	行尾锚定,用于模式的最右侧
^$	空行
^[[:space:]]*$	空行或包含空白字符的行
^PATTERN$ 	    用于模式匹配整行
\< 或 \b 	    匹配单词边界,表示锚定词首,其后面的字符必须作为单词首部出现
\> 或 \b        匹配单词边界,表示锚定词尾,其前面的字符必须作为单词尾部出现
\<PATTERN\>     匹配整个单词

2.4 分组或其他

()	分组

| 	或者
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

1、grep用法

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 行

2、grep案例

2.1 匹配qq号

[root@localhost ~]#grep -Eo "\b[0-9]{6,12}\b" 1.txt

2.2 匹配邮箱

[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

2.3 匹配手机号

[root@localhost ~]#grep -Eo "\b1[3456789][0-9]{9}\b" 1.txt 

2.4 查询 /etc/passwd 文件中有 root 的行

[root@localhost ~]#grep "root" /etc/passwd

2.5 将非#开头和非空白行的文本写入到其他文本

[root@localhost ~]#grep -Ev "^(#|$)" /etc/profile > 1.txt

2.6 匹配行首和行尾单词相同的行

[root@localhost ~]#grep "^\(.*\)\>.*\<\1$" /etc/passwd
[root@localhost ~]#grep -Eo "^(.*)\>.*\<\1$" /etc/passwd

2.7 多个模式条件匹配

#多个匹配条件之间的关系为或者
[root@localhost ~]#grep -e "root" -e "/bin/bash" /etc/passwd

2.8 提取出字符串中的所有数字

[root@localhost ~]#echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|grep -o [0-9]

2.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

1、sed概述

1.1 sed概念

  • sed 是一个流式文本编辑器,用于对文本进行替换、删除、插入等操作
  • 可在无交互的情况下实现相当复杂的文本处理操作
  • 被广泛应用于 Shell 脚本,以完成自动化处理任务

1.2 sed工作原理

  • 读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)
  • 执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定行的地址,否则 sed 命令将会在所有的行上依次执行
  • 显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空

1.3 sed优缺点

优点

  • 灵活强大的文本处理能力: sed 提供了丰富的文本处理命令和正则表达式支持,可以完成各种复杂的文本操作,如查找、替换、删除、插入等。它的功能强大且灵活,能够满足众多文本处理需求
  • 高效处理大型文件: sed 是基于流处理的工具,逐行读取和处理文本,因此在处理大型文件时非常高效,不会占用过多的内存和系统资源。这使得它适用于处理大量文本数据
  • 支持批量处理: sed 可以通过简单的命令一次性对多行文本进行处理,因此非常适合批量处理文本数据。它可以轻松地应用于一组文件或整个目录中的文件
  • 跨平台支持: sed 是一个跨平台的工具,可在不同的操作系统上(如Linux、UNIX、macOS等)使用。这使得它在各种环境中都能发挥作用,具有广泛的适用性。

缺点

  • 命令语法较复杂: sed 的命令语法相对较复杂,特别是对于初学者来说可能会有一定的学习曲线。对于一些复杂的处理任务,也可能需要深入了解正则表达式和高级命令才能灵活应用
  • 只能处理单行文本: sed 是基于行的文本处理工具,因此无法直接处理多行文本。它只能处理当前行,对于需要跨行操作的任务,可能会显得不够方便
  • 修改文件会覆盖原始数据: sed 默认情况下会直接修改文件内容,而不是将处理结果输出到标准输出。这意味着如果不小心操作,可能会不可逆地修改原始数据。因此,在使用 -i 选项时应格外小心
  • 不支持用户交互: sed 是一条命令行工具,通常在批处理环境下使用,并不支持与用户进行实时交互。这对于需要实时响应用户输入或交互的任务可能会有所不便

2、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 选项

3、sed搜索替换

脚本操作命令说明
s替换,替换指定字符,格式 s/文件旧内容/替换的内容/修饰符
yy字符转换,和 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

4、sed分组查找替换

[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/'

5、sed变量查找

#先定义变量再用sed命令调用该变量值
root@localhost ~]#name=root
[root@localhost ~]#sed -nr "/$name/p" /etc/passwd    
[root@localhost ~]#sed -nr '/'$name'/p' /etc/passwd  #两单引号也可以查询

6、使用sed工具修改配置文件

sed可以用于修改配置文件,它可以从标准输入或文件中读取文本,并对其进行编辑和转换

6.1 直接修改httpd的80端口

[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

 6.2 修改网卡名 

[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 

7、sed高级用法(了解)

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

1、awk的概述

awk是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令。 用于从文件、管道或标准输入中读取文本,并根据用户指定的模式和操作进行处理

  • 文本提取和转换: 可以用 awk 提取文件中的特定字段或行,并对其进行转换和格式化。
  • 数据分析和报告生成: 可以利用 awk 对结构化数据进行分析,并生成报告、统计信息或汇总数据。
  • 文本格式化和处理: 可以使用 awk 对文本进行格式化、排序、过滤和合并等操作。
  • 自定义文本处理: 可以编写自定义的 awk 脚本来实现特定的文本处理逻辑,满足特定的需求

2、awk基本用法

2.1 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变量赋值

2.2 基本打印用法(动作 print)

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

2.3 常见的内置变量

内置变量说明
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

2.5 模式PATTERN

(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}'

2.6 awk结合数组运用

在awk中,数组是一种非常有用的数据结构,用于存储和操作数据。awk中的数组是关联数组,也就是说它们可以使用字符串作为索引。

awk数组特性:

①awk的数组是关联数组(即key/value方式的hash数据结构),索引下标可为数值(甚至是负数、小数等),也可为字符串

  • 在内部,awk数组的索引全都是字符串,即使是数值索引在使用时内部也会转换成字符串
  • awk的数组元素的顺序和元素插入时的顺序很可能是不相同的

②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

2.7 条件判断(if)

在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

2.8 循环(for、while)

在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}'

2.9 awk脚本(了解)

#!/bin/awk -f
{if($3>=1000){print $3,$1}}

五、案例

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

2、统计当前连接主机数

[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}}'

3、过滤主机ip地址

[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}'

4、 提取13:01到14:02之间的日志

[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

5、提取下图ip地址及时间

[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}'

6、提取host.txt主机名再放回host.txt文件

[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

7、提取以数字形式显示/etc/passwd的权限

[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

8、 统计/etc/fstab文件中每个文件系统类型出现的次数

[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}}'

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/362488.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

回归预测 | Matlab实现CPO-GRU【24年新算法】冠豪猪优化门控循环单元多变量回归预测

回归预测 | Matlab实现CPO-GRU【24年新算法】冠豪猪优化门控循环单元多变量回归预测 目录 回归预测 | Matlab实现CPO-GRU【24年新算法】冠豪猪优化门控循环单元多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CPO-GRU【24年新算法】冠豪猪优化…

HiveSQL题——数据炸裂和数据合并

目录 一、数据炸裂 0 问题描述 1 数据准备 2 数据分析 3 小结 二、数据合并 0 问题描述 1 数据准备 2 数据分析 3 小结 一、数据炸裂 0 问题描述 如何将字符串1-5,16,11-13,9" 扩展成 "1,2,3,4,5,16,11,12,13,9" 且顺序不变。 1 数据准备 with da…

springboot144基于mvc的高校办公室行政事务管理系统设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

如何编写具有完备性的测试用例 ? 具体思路是什么 ? 全套解决方案打包呈现给你 。

设计测试用例应该算是测试人员最为主要的工作之一 &#xff0c;好的测试用例往往具有覆盖性强 &#xff0c;扩展性高以及复用性好等特点 。该如何设计出好的测试用例 &#xff1f;是我们每一位测试人员需要重点思考的问题 &#xff0c;下面是我对设计测试用例设计的思考 &#…

全国疫情实时监测系统(附源码)

目录 一.项目背景 1.有力支持疫情防控知识传播 2.迅速锁定“涉疫”人员流动轨迹 3.开展疫情发展态势预测与溯源 4.一图胜过千言万语&#xff01;&#xff01;&#xff01; 二.研究过程&#xff08;项目技术的利用&#xff09; 1.总述 2.所用技术介绍 2.1Python 2.2Pyt…

从零开始学Linux之gcc命令

首先我们需要知道有两种编程语言 编译型语言&#xff1a;要求必须提前将所有源代码一次性转换成二进制指令&#xff0c;也就是生成一个可执行程序&#xff0c;例如C、C、go语言、汇编语言等&#xff0c;使用的转换工具称为编译器。 解释型语言&#xff1a;一边执行一边转换&a…

解析电子名片二维码生成:便捷、灵活、个性化

在当今信息爆炸的时代&#xff0c;名片已经成为商务社交不可或缺的工具之一。然而&#xff0c;随着技术的不断发展&#xff0c;传统的纸质名片已经逐渐被电子名片生成二维码所取代。电子名片二维码不仅具备了传统名片的基本信息展示功能&#xff0c;更融合了数字化优势&#xf…

记一次java项目本地正常执行,打完包之后执行发现没有对应的类或配置的问题

1、起因 线上有个spark的任务出了问题&#xff08;该任务是通过sparkstreaming读取kafka中的数据&#xff0c;处理完之后推到es中&#xff09;&#xff0c;问题出在kafka中数据是有更新的&#xff0c;但是es中的对应索引中的数据却只更新到月初&#xff0c;因此我需要排查处理…

IDEA 取消参数名称提示、IDEA如何去掉变量类型提醒

一、IDEA 取消参数名称显示 取消显示形参名提示 例如这样的提示信息 二、解决方法 1、File—>Setting–>Editor—>Inlay Hints—>Java 去掉 Show Parameter hints for 前面的勾即可&#xff0c;然后Apply—>Ok 2、右键Disable Hints

爬虫学习笔记-Cookie登录古诗文网

1.导包请求 import requests 2.获取古诗文网登录接口 url https://so.gushiwen.cn/user/login.aspxfromhttp%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx # 请求头 headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like …

自定义注解实现记录日志功能(注解支持SpEL表达式)

一、首先创建个接口类Log import java.lang.annotation.*;/*** description: 自定义操作日志记录注解* author xizc**/ Target({ ElementType.PARAMETER, ElementType.TYPE, ElementType.METHOD }) Retention(RetentionPolicy.RUNTIME) Inherited Documented public interface …

JUnit

前言&#xff1a;自动化就是selenium脚本来实现的&#xff0c;JUnit是java的单元测试工具&#xff0c;只不过我们在实现自动化的时候需要借助一下JUnit库里面提供的一些方法。 1、Test Test &#xff1a;表示方法是测试方法&#xff0c;执行当前这个类的时候&#xff0c;会自动…

Unity之做一个最简单的FPS游戏demo

目录 &#x1f60b;FPS游戏Demo &#x1f4a4;1.新建FPS模板项目 ⚒️2.装备枪 &#x1f4a3;3.设置射击功能 &#x1f4fa;4.制造一个子弹预制体 &#x1f3ae;5.发射子弹 说起来小编学Unity差不多一个月了&#xff0c;都是利用上班摸鱼时间学的&#xff08;doge.jpg&…

java+springboot校园体育场地预约预订使用系统vue+ssm

研究内容和研究方法 1.研究内容 网站主要包括管理员和用户两个部分&#xff0c;用户可以登录与注册自己的基本信息、查询哪些场地可以使用、提前预约场地、取消预约的场地、使用完场地后进行缴费。管理员可以审批用户的注册信息、对用户信息进行增删改查、查询场地的使用情况、…

【C++干货基地】C++引用与指针的区别:深入理解两者特性及选择正确应用场景

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

秋招面试—JS篇

2024 JavaScript面试题 1.new 操作符的工作原理 ①.创建一个新的空对象 ②.将这个对象的原型设置为函数的 prototype 对象 ③.让函数的this指向该对象&#xff0c;为函数添加属性和方法 ④.最后返回这个对象 2.什么是DOM&#xff0c;什么是BOM? DOM&#xff1a;文档对象…

AI日报:谷歌的“双子时代”:将第二代人工智能嵌入其所做的一切

谷歌强大的大型多模式模式Gemini正在进军搜索、广告、云、Bard等领域。Bard的付费订阅即将到来吗&#xff1f; 文章目录 一览Bard订阅即将到来&#xff1f;一代人工智能进入谷歌广告YouTube正在崛起收入上升但股价下跌 一览 谷歌首席执行官、母公司Alphabet的桑达尔皮查伊表示&…

Kotlin 协程:用源码来理解 ‘viewModelScope‘

Kotlin 协程&#xff1a;用源码来理解 ‘viewModelScope’ Kotlin 协程是 Kotlin 语言的一大特色&#xff0c;它让异步编程变得更简单。在 Android 开发中&#xff0c;我们经常需要在后台线程执行耗时操作&#xff0c;例如网络请求或数据库查询&#xff0c;然后在主线程更新 UI…

VBoxManage 命令行使用

VBoxManage&#xff1a; 序号命令作用1VBoxManage list vms# 查看当前所有虚拟机2VBoxManage list runningvms # 查看当前正在运行的虚拟机3VBoxManage startvm 虚拟机名 --type gui # 启动虚拟机4VBoxManage startvm 虚拟机名 --type headless# 无前端图形界面方式启动虚拟机…

Elasticsearch:构建自定义分析器指南

在本博客中&#xff0c;我们将介绍不同的内置字符过滤器、分词器和分词过滤器&#xff0c;以及如何创建适合我们需求的自定义分析器。更多关于分析器的知识&#xff0c;请详细阅读文章&#xff1a; 开始使用 Elasticsearch &#xff08;3&#xff09; Elasticsearch: analyzer…