文本编辑工具 vim

vi 和 vim 简介

​ vi 是文本编辑器,vim 是 vi 的增强版。

image-20220817084311877

一、vim 的常见模式和转换

1、三种常见模式

  • 命令或普通模式 vim 打开一个文件的默认启动模式,可以实现光标移动、剪切/粘贴文本
  • 插入或编辑模式 修改文本
  • 扩展命令或命令(末)行模式 保存、退出等

2、模式之间的转换

命令模式 —> 插入模式

1
2
3
4
5
6
i 	insert,在光标所在处插入
I 在当前光标所在行的行首输入
a append,在光标所在处后面插入
A 在当前光标所在行的行尾输入
o 在光标所在行的下方插入一个新行
O 在当前光标所在行的上方打开一个新行

插入模式 —> 命令模式 Esc

命令模式 —> 末行模式 :

末行模式 —> 命令模式 Esc,Enter

示例:插入颜色字符

1
2
3
4
5
6
7
8
9
10
1、切换至插入模式
2、按ctrl+v+[ 三个键,显示^[
3、后续输入颜色信息
4、切换至扩展命令模式,保存退出
5、cat 文件内容时看见相关颜色文本内容

[root@Rocky8-mini ~]# vim color.txt
^[[1;31mHello^[[0m
# 结果如下图
[root@Rocky8-mini ~]# cat color.txt

image-20221008222224417

二、末行模式

1
2
3
4
5
6
7
8
9
10
# 按 : 进入末行模式
[root@Rocky8-mini ~]# vi /etc/shadow
1 root:$6$gwZKY4RbKMpHlO7S$FztMVac/skadP5/ALb.KQvjNRS4CvFcpiD8FfGPPMcbPahW/LfsEXHQXfz.f3eTVpMFvaDQCPLeX/dAPElpjK0::0:99999:7:::
2 bin:*:18700:0:99999:7:::
3 daemon:*:18700:0:99999:7:::
···
···
26 saslauth:!!:19078::::::
~
:

2.1 末行模式基本命令

1
2
3
4
5
6
7
8
9
10
w          保存文件
wq 写入并退出
x 写入并退出
X 加密
q 退出
q! 强制退出
r filename 读入一个文件内容到当前文件的光标所在处
w filename 将当前文件内容写入另一个文件中
!command 在不退出vim的情况下,临时执行一个命令
r!command 读入一个命令的输出到当前文件中

2.2 地址定界

格式 :start_pos,end_pos CMD

2.2.1 地址定界格式

1
2
3
4
5
6
7
8
9
10
11
12
#        具体第#行
#,# 从第几行到第几行
#,+# 例:3,+3 从第三行到第六行
. 当前行
$ 最后一行
.,$-1 当前行到倒数第二行
% 全文

/PATTERN/ 从当前行向下查找,直到匹配查找到的字符串。支持正则表达式
/pat1/,/pat2/ 从第一个匹配到的模式开始到第二次匹配到的模式结束
#,/pat/ 从#行开始,到匹配到pattern的行结束
/pat/,$ 从匹配到的第一个pat开始到文件末尾的所有行

2.2.2 地址定界后跟编辑命令

1
2
3
4
5
6
7
8
9
d		删除
y 复制
w file 将匹配到的行另存到指定文件中
r file 在指定位置插入指定文件的内容

# 删除2~5行
:2,5d
# 在第五行读入指定文件的内容,在指定行下方插入
:5 r /etc/shadow

2.3 查找替换

2.3.1 查找

1
2
3
4
5
6
/PATTERN	从当前光标所在处向文件尾部查找;
?PATTERN 从当前光标所在处向文件首部查找;
n:与命令同方向
N:与命令反方向
例:
?\<love\> 从当前光标处向文件首部查找love这个单词

2.3.2 查找并替换

1
2
3
4
5
6
7
8
9
10
11
12
13
s: 在末行模式下完成查找替换操作
s/要查找的内容/替换为的内容/修饰符
要查找的内容:可使用模式
替换为的内容:不能使用模式,但可以使用\1, \2, ...等后向引用符号;还可以使用“&”引用前面查找时查找到的整个内容;
修饰符:
i: 忽略大小写
g: 全局替换;默认情况下,每一行只替换第一次出现;
查找替换中的分隔符/可替换为其它字符,否则就要用到转义符,例如
s@@@
s###
例:
:%s/\/etc\/fstab/\/var\/log/g 或
:%s@/var/log@/etc/fstab@g

2.4 定制 vim 工作特性

使用末行模式的配置只是对当前vim进程有效,可将配置存放在文件中永久保存。

配置文件:

1
2
/etc/vimrc    全局
~/.vimrc 个人

2.4.1 行号

1
2
显示:set number, 简写为set nu
取消显示:set nonumber, 简写为set nonu

2.4.2 忽略字符大小写

1
2
启用:set ic
不忽略:set noic

2.4.3 自动缩进

1
2
启用:set ai
禁用:set noai

2.4.4 复制保留模式

1
2
启用:set paste
禁用:set nopaste

2.4.5 显示Tab ^l 和换行符 $ 显示

1
2
启用:set list
禁用:set nolist

2.4.6 高亮搜索

1
2
启用:set hlsearch
禁用:set nohl

2.4.7 语法高亮

1
2
启用:syntax on
禁用:syntax off

2.4.8 文件格式

1
2
3
启用windows格式:set fileformat=dos
启用unix格式:set fileformat=unix
简写 set ff=dos|unix

2.4.9 Tab 用空格代替

1
2
启用:set expandtab(set et) 默认8个空格
禁用:set noet

2.4.10 Tab 用指定空格的个数代替

1
启用:set ts=#   #为空格的个数

2.4.11 设置缩进宽度

1
set sw=#	#为空格的个数

2.4.12 设置文本宽度

1
2
set textwidth=65 (vim only) #从左向右计数
set wrapmargin=15 #从右到左计数

2.4.13 设置光标所在行的标识线

1
2
启用:set cul
禁用:set nocul

2.4.14 加密

1
2
启用:set key=PASSWORD
禁用:set key=

2.4.15 了解更多

1
2
set 
set all

三、命令模式

3.1 退出vim

1
2
ZZ	保存退出
ZQ 不保存退出

3.2 光标跳转

3.2.1 字符间跳转

1
2
3
4
5
h	左
l 右
j 下
k 上
#COMMAND 跳转到由#指定的个数的字符

3.2.2 单词间跳转

1
2
3
4
w	下一个单词的词首
e 当前或下一个单词的词尾
b 当前或前一个单词的词首
#COMMAND 由#指定一次跳转的单词数

3.2.3 当前页跳转

1
2
3
4
5
6
H	页首
M 页中间行
L 页底
zt 将光标所在当前行移到屏幕顶端
zz 将光标所在当前行移到屏幕中间
zb 将光标所在当前行移到屏幕底端

3.2.4 行首行尾跳转

1
2
3
^	跳转至行首的第一个非空白字符
0 跳转至行首
$ 跳转至行尾

3.2.5 行间移动

1
2
G	最后一行
gg 第一行

3.2.6 句间移动

1
2
)下一句
( 上一句

3.2.7 段落间移动

1
2
}	下一段
{ 上一段

3.2.8 命令模式翻屏操作

1
2
3
4
Ctrl+f 向文件尾部翻一屏,相当于Pagedown
Ctrl+b 向文件首部翻一屏,相当于Pageup
Ctrl+d 向文件尾部翻半屏
Ctrl+u 向文件首部翻半屏

3.3 字符编辑

1
2
3
4
5
x      剪切光标处的字符
#x 剪切光标处起始的#个字符
xp 交换光标所在处的字符及其后面字符的位置
~ 转换大小写
J 删除当前行后的换行符

3.4 替换命令

1
2
r		只替换光标所在处的一个字符
R 切换成REPLACE模式(末行有 -- REPLACE -- 提示),按Esc键回到命令模式

3.5 删除命令(实际为剪切)

1
2
3
4
5
6
7
8
9
10
d		删除,可通过光标跳转字符,实现范围删除
d$ 删除到行尾
d^ 删除到非空行首
d0 删除到行首
dw
de
db
dd 删除光标所在的行
#dd 多行删除
D 从当前光标位置一直删除到行尾,等同于d$

3.6 复制命令

1
2
3
4
5
6
7
8
9
10
11
12
y 复制,行为相似于d命令
y$
y0
y^
ye
yw
yb
#COMMAND
yy:复制行
#yy 复制多行

------ 类似于d命令 ------

3.7 粘贴命令

1
2
p 缓冲区存的如果为整行,则粘贴当前光标所在行的下方;否则,则粘贴至当前光标所在处的后面
P 缓冲区存的如果为整行,则粘贴当前光标所在行的上方;否则,则粘贴至当前光标所在处的前面

3.8 改变命令

使用 c 命令后会进入到插入模式,用法类似于 d 命令

1
2
3
4
5
6
7
8
9
10
c$
c^
c0
cb
ce
cw
#COMMAND
cc #删除当前行并输入新内容,相当于S
#cc
C #删除当前光标到行尾,并切换成插入模式,相当于c$

3.9 撤销更改

1
2
3
4
5
6
u 撤销最近的更改,相当于windows中ctrl+z
#u 撤销之前多次更改
U 撤消光标落在这行后所有此行的更改
Ctrl-r 重做最后的“撤消”更改,相当于windows中crtl+y
. 重复前一个操作
#. 重复前一个操作#次

四、可视化模式

进入到可视化模式,末行有“– – VISUAL – –”指示

可视化模式的类型

  • v 面向字符 – VISUAL –
  • V 面向整行 – VISUAL LINE –
  • ctrl+v 面向块 – VISUAL BLOCK –

进入到可视化模式,被选中的文字可被删除,复制,变更,过滤,搜索,替换等

范例

1
2
3
4
5
6
7
1、在文件指定行的行首插入#
- 先将光标移动到指定的第一行的行首
- 输入ctrl+v 进入到可视化模式
- 向下移动光标,选中希望操作的每一行的第一个字符
- 输入大写字母 I 切换至插入模式
- 输入 #
- 按 Esc 键

五、多文件模式

1
2
3
4
5
6
7
8
vim FILE1 FILE2 FILE3 ...
:next 下一个
:prev 前一个
:first 第一个
:last 最后一个
:wall 保存所有
:qall 不保存退出所有
:wqall保存退出所有

六、多窗口模式

多文件模式

1
2
3
4
5
6
7
vim FILE1 FILE2 FILE3 ...
:next 下一个
:prev 前一个
:first 第一个
:last 最后一个
:wall 保存所有
:qall 退出所有

窗口分割模式

1
2
3
4
5
6
7
8
9
10
vim -o|-O FILE1 FILE2 ...
-o: 水平分割
-O: 垂直分割
在窗口间切换:Ctrl+w, Arrow
单文件窗口分割:
Ctrl+w,s: split, 水平分割
Ctrl+w,v: vertical, 垂直分割
ctrl+w,q:取消相邻窗口
ctrl+w,o:取消全部窗口
:wqall 退出

文本常见处理工具

一、查看文件内容

1.1 查看文本文件内容

1.1.1 cat

NAME
cat - concatenate files and print on the standard output

1
2
3
4
5
6
[option]
-E:显示行结束符$
-A:显示所有控制符
-n:对显示出的每一行进行编号
-b:只对非空行进行编号
-s:压缩连续的空行成一行

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
------------ 支持标准输入 -----------
[root@Rocky8-mini ~]# cat > file4
aaa
ss
dd
gg
[root@Rocky8-mini ~]# cat file4
aaa
ss
dd
gg
[root@Rocky8-mini ~]# cat >> file4 << EOF // 多行重定向
> line5
> EOF
[root@Rocky8-mini ~]# cat file4
aaa
ss
dd
gg
line5

1.1.2 nl(相当于 cat -b)

NAME
nl - number lines of files

1
2
3
4
5
6
7
8
9
10
11
12
[root@Rocky8-mini ~]# cat -n file2
1 1
2 2
3 3
4
5 5
[root@Rocky8-mini ~]# nl file2 # nl 只对非空行进行编号
1 1
2 2
3 3

4 5

1.1.3 tac

NAME
tac - concatenate and print files in reverse

1
2
3
4
5
6
7
8
9
10
11
12
[root@Rocky8-mini ~]# tac file1
5
4
3
2
1
[root@Rocky8-mini ~]# cat file1
1
2
3
4
5

1.1.4 rev

NAME
rev - reverse lines characterwise

1
2
3
4
5
6
7
8
9
[root@Rocky8-mini ~]# cat file
01234
56789
[root@Rocky8-mini ~]# tac file
56789
01234
[root@Rocky8-mini ~]# rev file
43210
98765

1.2 查看非文本文件内容

1.2.1 hexdump

1
2
3
4
5
6
7
8
9
10
11
12
13
14
NAME
hexdump - display file contents in hexadecimal, decimal, octal, or ascii
SYNOPSIS
hexdump [options] file...
------------------------------------------------------------
[root@Rocky8-mini ~]# hexdump -C -n 5 /dev/sda
00000000 eb 63 90 10 8e |.c...|
00000005
[root@Rocky8-mini ~]# echo {a..f} | hexdump -C
00000000 61 20 62 20 63 20 64 20 65 20 66 0a |a b c d e f.|
0000000c
[root@Rocky8-mini ~]# echo {a..f} |tr -d ' ' | hexdump -C
00000000 61 62 63 64 65 66 0a |abcdef.|
00000007

1.2.2 od

1
2
3
4
5
6
7
8
9
10
11
12
13
14
NAME
od - dump files in octal and other formats
--------------------------------------------------------------------
[root@Rocky8-mini ~]# echo {a..z} | tr -d ' '|od -t x
0000000 64636261 68676665 6c6b6a69 706f6e6d
0000020 74737271 78777675 000a7a79
0000033
[root@Rocky8-mini ~]# echo {a..z} | tr -d ' '|od -t x1
0000000 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70
0000020 71 72 73 74 75 76 77 78 79 7a 0a
0000033
[root@Rocky8-mini ~]# echo {a..f} | tr -d ' ' |od -t x1z
0000000 61 62 63 64 65 66 0a >abcdef.<
0000007

1.2.3 xxd

1
2
3
4
5
NAME
xxd - make a hexdump or do the reverse.
-------------------------------------------------------------------
[root@Rocky8-mini ~]# echo {a..f} | tr -d ' ' | xxd
00000000: 6162 6364 6566 0a abcdef.

二、分页查看文件内容

  • more
  • less
1
2
3
more 和 less 都可实现文件的翻页
使用 more 查看文件到末尾时会自动退出,而 less 不会
less 查看文件时,支持使用模式匹配 /文本 搜索文本 n/N 跳到下一个 或 上一个匹配

三、显示文本前或后行内容

3.1 head

选项:

1
2
-c #	指定获取前#字节
-n # 指定获取前#行,#如果为负数,表示从文件头取到倒数第#行,不包括倒数第#行

例:

1
2
3
4
5
6
7
8
9
[root@Rocky8-mini ~]# cat file1
1
2
3
4
5
[root@Rocky8-mini ~]# head -n -3 file1
1
2

3.2 tail

选项

1
2
3
4
-c #	指定获取后#个字节
-n # 指定获取后#行,如果#前有加号,表示从第#行开始到文件结束
-f 跟踪显示文件中的内容,当文件删除在新建一个同名文件时,无法继续跟踪
-F 也可跟踪显示文件中的内容,当文件删除又新建一个同名文件时可继续追踪

实例

1
2
3
4
5
6
7
8
9
[root@Rocky8-mini ~]# cat file1
1
2
3
4
5
[root@Rocky8-mini ~]# tail -n +4 file1
4
5

四、按列抽取文本 cut

常用选项

1
2
3
4
5
6
7
8
-d	DELIMITER:指明分隔符,默认为 Tab
-f FILEDS:
#: 第#个字段
#,#: 指定多个不连续的字段,如 1,3,5
#-#: 连续的多个字段
混合使用: 1-3,7
-c 按字符切割
--output-delimiter=STRING 指定输出分隔符

实例:

1
2
3
4
5
6
7
8
9
[root@Rocky8-mini ~]# df | tail -n $(echo `df | wc -l`-1|bc)
devtmpfs 897476 0 897476 0% /dev
tmpfs 916616 0 916616 0% /dev/shm
tmpfs 916616 8884 907732 1% /run
tmpfs 916616 0 916616 0% /sys/fs/cgroup
/dev/mapper/rl-root 31441920 1849564 29592356 6% /
/dev/mapper/rl-data 17410832 45084 16458280 1% /data
/dev/sda1 1038336 216624 821712 21% /boot
tmpfs 183320 0 183320 0% /run/user/0

五、合并多个文件 paste

常用选项

1
2
-d DELIMITER: 指定分隔符,默认为 Tab
-s 所有行合成一行显示

范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@Rocky8-mini ~]# cat f1 
2
3
4
[root@Rocky8-mini ~]# cat f2
b
c
d
[root@Rocky8-mini ~]# paste -d ' ' f1 f2
2 b
3 c
4 d
[root@Rocky8-mini ~]# paste -s -d ' ' f1 f2
2 3 4
b c d

六、分析文本的工具

6.1 文本统计数据 wc

常用选项

1
2
3
4
-l	只计数行数
-w 只计数单词总数
-c 统计字节总数
-L 显示文件中最长行的长度

实例:

1
2
3
[root@Rocky8-mini ~]# wc /etc/passwd
27 46 1262 /etc/passwd
行数 单词数 字节数

6.2 文本排序 sort

常用选项

1
2
3
4
5
6
7
8
-r,--reverse	reverse the result of comparisons
-R 随机排序
-n 按照数字大小整理
-h 易读性排序,如 2M 1K
-f 忽略字符大小写
-u 去重
-t 指定字段分隔符
-k# 对指定分隔符后的#列进行排序

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
============== 统计分区的利用率 ==============
[root@Rocky8-mini ~]# df |tail -n $(echo `df | wc -l` -1 | bc) | tr -s ' '| cut -d' ' -f1,5 | sort -n -t' ' -k2 -r
/dev/sda1 21%
/dev/mapper/rl-root 7%
tmpfs 1%
/dev/mapper/rl-data 1%
tmpfs 0%
tmpfs 0%
tmpfs 0%
devtmpfs 0%

============== 有两个文件,a.txt和b.txt,合并两个文件,并输出时确保每个数字唯一 =============
[root@Rocky8-mini ~]# cat a.txt
2
3
4
[root@Rocky8-mini ~]# cat b.txt
1
3
4
5
[root@Rocky8-mini ~]# cat a.txt b.txt | sort -u
1
2
3
4
5

6.3 文本去重 uniq

常用选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-c	显示每行重复出现的次数
-d 仅显示重复过的行
-u 仅显示没有重复的行
# 注:重复为连续且相同 #
[root@Rocky8-mini ~]# cat file3
22
1
3
43
23
4
5
10
1
1
[root@Rocky8-mini ~]# uniq -d file3
1
[root@Rocky8-mini ~]# uniq -u file3
22
1
3
43
23
4
5
10

常与 sort 命令一起使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-- 并发连接最多的远程主机 --
[root@Rocky8-mini ~]# ss -nt | grep "ESTAB" | tr -s ' ' : | cut -d: -f6 | sort | uniq -c | sort -nr
4 192.168.119.1
2 192.168.119.158
1 192.168.119.147

-- 取两个文件的相同和不同的行 --
[root@Rocky8-mini ~]# cat a.txt
2
3
4
[root@Rocky8-mini ~]# cat b.txt
1
3
4
5

# 仅显示两个文件中相同的内容
[root@Rocky8-mini ~]# cat a.txt b.txt | sort | uniq -d
3
4

# 显示两个文件中没有重复的
[root@Rocky8-mini ~]# cat a.txt b.txt | sort | uniq -u
1
2
5

6.4 比较文件

6.4.1 diff

-u 选项,使用 unified 格式显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@Rocky8-mini ~]# cat file1
root
nginx
wh
wuhao
harry
[root@Rocky8-mini ~]# cat file2
mage
root
wuhao
apache
[root@Rocky8-mini ~]# diff -u file1 file2
--- file1 2022-03-22 08:35:52.270539575 -0400
+++ file2 2022-03-22 08:38:20.195502598 -0400
@@ -1,5 +1,4 @@
+mage
root
-nginx
-wh
wuhao
-harry
+apache
[root@Rocky8-mini ~]# diff -u file1 file2 > f.patch
[root@Rocky8-mini ~]# rm -f file2 // 删除file2文件
-- 先将 file1 文件备份成file1.org,然后根据f.patch文件和file1文件恢复原来的file2文件,但此时名称命名为file1 --
[root@Rocky8-mini ~]# patch -b file1 f.patch
patching file file1
[root@Rocky8-mini ~]# cat file1 // 恢复的file2文件
mage
root
wuhao
apache
[root@Rocky8-mini ~]# cat file1.orig
root
nginx
wh
wuhao
harry

6.4.2 patch

6.4.3 vimdiff

6.4.4 cmp

练习

1、找出ifconfig “网卡名” 命令结果中本机的IPv4地址

1
2
[root@Rocky8-mini ~]# ifconfig ens33 | tr -s ' ' | cut -d' ' -f3 | sort -nr | head -1
192.168.119.128

2、查出分区空间使用率的最大百分比值

1
2
[root@Rocky8-mini ~]# df |tail -n $(echo `df | wc -l` -1 | bc) | tr -s ' '| cut -d' ' -f5 | sort -nr | head -n1
21%

3、查出用户UID最大值的用户名、UID及shell类型

1
2
[root@centos7-mini3 ~]# sort -t: -k3 -n /etc/passwd | tail -1 | cut -d: -f 1,3,7
wh:1000:/bin/bash

4、查出/tmp的权限,以数字方式显示

1
2
[root@centos7-mini3 ~]# stat /tmp | tr -s '/(' ' ' | cut -d ' ' -f 2 | sed  -n '4p'
1777

5、统计当前连接本机的每个远程主机IP的连接数,并按从大到小排序

1
2
3
4
[root@Rocky8-mini ~]# ss -nt | grep "ESTAB" | tr -s ' ' : | cut -d: -f6 | sort | uniq -c | sort -nr
4 192.168.119.1
2 192.168.119.158
1 192.168.119.147

正则表达式

通配符通常用来匹配文件名,而正则表达式是用来匹配文本中的字符串。

正则表达式分类:

  • 基本正则表达式
  • 扩展正则表达式

正则表达式的元字符分类:字符匹配、匹配次数、位置锚定、分组

注:grep命令的使用见文本处理三剑客文章

一、基本正则表达式元字符

1.1 字符匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.	匹配任意单个字符,可以使一个汉字
[] 匹配指定范围内的任意单个字符
[^] 匹配指定范围外的任意单个字符
[:alnum:] 字母和数字
[:alpha:] 任意大小写字母
[:lower:] 任意小写字母
[:upper:] 任意大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 包括空格、制表符、换行符、回车符等各种类型的空白
[:cntrl:] 不能打印的控制字符(退格、删除、警铃···)
[:digit:] 十进制数字
[:xdigit:] 十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号

\w #匹配单词构成部分,等价于[_[:alnum:]]
\W #匹配非单词构成部分,等价于[^_[:alnum:]]
\S #匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\s #匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意
Unicode 正则表达式会匹配全角空格符

1.2 匹配次数

用在要指定次数的字符后面,用于指定前面的字符要出现的次数

1
2
3
4
5
6
7
8
*		匹配前面的字符任意次,贪婪模式:尽可能长的匹配
.* 任意长度的任意字符
\? 匹配其前面的字符出现0次或1
\+ 匹配其前面的字符至少出现1
\{n\} 匹配前面的字符n次
\{m,n\} 匹配前面的字符至少m次,最多n次
\{,n\} 匹配前面的字符最多n次
\{m,\} 匹配前面的字符至少m次
  1. 非捕获组标志
    • 当问号与冒号一起使用,形如 (?:...) 时,它创建了一个非捕获组,其中的内容将被当作一个整体来匹配,但匹配结果不会被捕获到单独的组中。

1.3 位置锚定

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

1
2
3
4
5
6
7
8
9
10
11
^               行首锚定,用于模式的最左侧
$ 行尾锚定,用于模式的最右侧
^PATTERN$ 模式匹配整行
^$ 匹配空行
^[[:space:]] 空白行
\< 词首锚定
\> 词尾锚定
\<PATTERN\> 匹配整个单词

注:单词是由字母、数字、下划线组成,其他均为单词的分隔符
如:http_122、788hhh 为单词;http-122788:hhh 为两个单词

实例

1
2
3
----------- 排除掉空行和"#"开头的行 -----------
[root@Rocky8-mini ~]# grep -v '^$' /etc/profile|grep -v '^#'
[root@centos8 ~]#grep '^[^$#]' /etc/profile

1.4 分组、或者

分组:()将多个字符捆绑在一起,当作一个整体处理,如:\(root\)

后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名方式为:\1,\2,\3,…(\1 表示从左侧第一个左括号与之匹配的右括号之间的模式匹配到的内容)

Example:

1
2
3
4
	\(ab\+\(xy\)*\):
\1: ab\+\(xy\)*
\2:xy
后向引用:引用前面的分组括号中的模式所匹配到的字符(也就是匹配到的结果),而非模式本身。

或者:\|

Example:

1
2
3
a\|b				a或b
c\|cat c或cat
\(C\|c\)at Cat或cat

实例:

1
2
3
4
5
-------------------- 排除空行和'#'开头的行 ----------------------
grep -v '^#' /PATH/TO/FILE |grep -v ^$
grep -v '^#\|^$' /PATH/TO/FILE
grep -v '^\(#\|$\)' /PATH/TO/FILE
grep "^[^#]" /PATH/TO/FILE

正则表达式练习

1、显示/proc/meminfo文件中以大小s开头的行(要求:使用两种方法)

1
2
[root@Rocky8-mini tmp]# grep "^[Ss]" /proc/meminfo
[root@Rocky8-mini tmp]# grep -i "^s" meminfo /proc/meminfo

2、显示/etc/passwd文件中不以/bin/bash结尾的行

1
[root@Rocky8-mini tmp]# grep -v  "/bin/bash$" /etc/passwd

3、显示用户rpc默认的shell程序

1
[root@Rocky8-mini ~]# grep "^\<rpc\>" /etc/passwd | cut -d: -f7

4、找出/etc/passwd中的两位或三位数

1
[root@Rocky8-mini ~]# grep "\<[0-9]\{2,3\}\>" /etc/passwd

5、显示CentOS7的/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面有非空白字符的行

1
[root@centos7 ~]# grep "^[[:space:]]\+[[:alnum:]].*" /etc/grub2.cfg

6、找出“netstat -tan”命令结果中以LISTEN后跟任意多个空白字符结尾的行

1
2
3
[root@Rocky8-mini ~]# netstat -tan | grep "\(LISTEN[[:space:]]*\)$"
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp6 0 0 :::22 :::* LISTEN

7、显示CentOS8上所有UID小于1000以内的用户名和UID

1
[root@Rocky8-mini ~]# cat /etc/passwd | cut -d: -f1,3 | grep "\<[0-9]\{1,3\}\>"

8、添加用户bash、testbash、basher、sh、nologin(其shell为/sbin/nologin),找出/etc/passwd用户名和shell同名的行

1
[root@Rocky8-mini ~]# grep "^\(\<[[:alnum:]]\+\>\).*\1$" /etc/passwd

9、利用df和grep,取出磁盘各分区利用率,并从大到小排序

1
2
3
4
[root@Rocky8-mini ~]# df | grep "^/dev" | tr -s ' ' % | cut -d% -f1,5 --output-delimiter='   ' | sort -nr
/dev/sda1 21
/dev/mapper/rl-root 7
/dev/mapper/rl-data 1

二、扩展正则表达式元字符

扩展正则表达式元字符同基本正则表达式元字符,只是不需要加转义字符,词首锚定和词尾锚定仍然需要。

扩展正则表达式练习

1、显示三个用户root、mage、wang的UID和默认shell

1
2
3
4
[root@centos7 ~]# grep -E "^(\<root\>|\<mage\>|\<wang\>)" /etc/passwd | cut -d: -f3,7
0:/bin/bash
1000:/bin/bash
1001:/bin/bash

2、找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行

1
[root@centos7 ~]# grep -E "^[_[:alnum:]]+\(\)" /etc/rc.d/init.d/functions 

3、使用egrep取出/etc/rc.d/init.d/functions中其基名

1
2
3
4
[root@centos7 ~]# basename /etc/rc.d/init.d/functions
functions
[root@centos7 ~]#echo "/etc/rc.d/init.d/functions/" | grep -E -o "[^/]+/?$" | cut -d/ -f1
functions

4、使用egrep取出上面路径的目录名

1
2
3
[root@centos7 ~]# dirname /etc/rc.d/init.d/functions
/etc/rc.d/init.d

5、统计last命令中以root登录的每个主机IP地址登录次数

1
[root@Rocky8-mini ~]# last | grep -E '^\<root\>.*([0-9]{1,3}\.){3}[0-9]{1,3}'|tr -s ' '|cut -d' ' -f3| sort | uniq -c

6、利用扩展正则表达式分别表示0-9、10-99、100-199、200-249、250-255

1
2
3
4
5
grep -E "\<[0-9]\>" num.txt
grep -E "\<[0-9]{2}\>" num.txt
grep -E "\<1[0-9]{2}\>" num.txt
grep -E "\<2[0-4][0-9]\>" num.txt
grep -E "\<25[0-5]\>" num.txt

7、显示ifconfig命令结果中所有IPv4地址

1
[root@Rocky8-mini ~]# ifconfig | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}"

8、将此字符串:welcome to wuhao linux 中的每个字符去重并排序,重复次数多的排到前面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@Rocky8-mini ~]# echo ‘welcome to wuhao linux’ | grep -o "[[:alpha:]]" | sort | uniq -c | sort -nr
3 o
2 w
2 u
2 l
2 e
1 x
1 t
1 n
1 m
1 i
1 h
1 c
1 a