1. 文本编辑工具vim
1.1 vim介绍
在Linux中我们经常编辑修改文本文件, 即由ASCII, Unicode或其他编码的纯文字的文件. Vim是一款使用最多的Linux平台的文本编辑工具
vim安装:
# 最小化安装的系统, 需要单独安装vim包
[root@demo-c8 ~]# rpm -ql vim-enhanced
/etc/profile.d/vim.csh
/etc/profile.d/vim.sh
/usr/bin/rvim
/usr/bin/vim
/usr/bin/vimdiff
/usr/bin/vimtutor
/usr/lib/.build-id
/usr/lib/.build-id/7f
/usr/lib/.build-id/7f/37d6ce6c2273cc7bdf383618236c268dbeb092
1.2 使用 vim 初步
1.2.1 vim 命令格式
vim [OPTION]... FILE...
常用选项:
vim打开文件, 光标默认处在第一行行首
+# 打开文件后,让光标处于第#行的行首,`vim + FILE`: 打开文件后, 光标处于最后一行行首.
+/PATTERN 让光标处于第一个被PATTERN匹配到的行的行首
-b file 二进制方式打开文件
-d file1 file2... 比较多个文件,相当于 vimdiff
-m file 只读打开文件
-e file 直接进入ex模式,相当于执行ex file
-y file Easy mode (like "evim", modeless),直接可以操作文件,ctrl+o:wq|q! 保存和不保存退出
说明:
- 如果该文件存在,文件被打开并显示内容
- 如果该文件不存在,当编辑后第一次存盘时创建它
1.2.2 三种主要模式和转换
vim 是一个模式编辑器,其行为是依赖于 vim的模式
三种常见模式:
- 命令或普通(Normal)模式:默认模式,可以实现移动光标,剪切/粘贴文本
- 插入(Insert)或编辑模式:用于修改文本
- 扩展命令(extended command )或命令(末)行模式:保存,退出等
模式转换
- 命令模式 --> 插入模式
i insert, 在光标所在处输入
I 在当前光标所在行的行首输入
a 在当前光标所在处后面输入
A 在当前光标所在行行尾输入
o 在当前光标所在行的下方打开一个新行
O 在当前光标所在行的上方打开一个新行
行首插入: I
行尾插入: A
上一行插入: O
下一行插入: o
光标处插入: i
光标处下一位插入: a
- 插入模式 --
ESC
-- 命令模式 - 命令模式 --
:
-- 扩展命令模式 - 扩展命令模式 --
ESC
-- 命令模式
1.3 扩展命令模式
按冒号 " : " 可以进入Ex模式,创建一个命令提示符: 处于底部的屏幕左侧
1.3.1 扩展命令模式基本命令
w 写(存)磁盘文件
wq 写入并退出
x 写入并退出
X 加密
q 退出
q! 不存盘退出,未保存更改都将丢失
r filename 读取文件内容到当前文件中, 在光标所在行下一行插入
范例: :r/data/prac/test.txt, 如果读取的是和当前文件在同一个目录的文件, 要使用./文件名
w filename 将当前文件内容写入另一个文件
范例: :w/data/prac/test.txt, 如果写入的是和当前文件在同一个目录的文件, 要使用./文件名. 如果目标文件不存在, 会自动创建文件, 并写入内容
如果目标文件存在, 那么就要加!,去覆盖掉原文件内容, :w!./f1.txt
!command 执行命令, 打印在屏幕上,但是不会追加到文件中
r!command 读取命令的输出. 将命令的输出追加到鼠标当前行的下一行
1.3.2 地址定界
在末行模式执行
格式:
地址界定后需要接命令, 来完成操作
:start_pos,end_pos CMD
1.3.2.1 地址定界格式
在末行模式输入以下格式
1. # 将光标移动到第几行的行首, :2就是移动到第二行行首
2. . 将光标移动到当前行的行首
3. $ 将光标移动到最后一行行首, %也是移动到最后一行行首
4. $-# 将光标移动到倒数第#+1行, $-1就是倒数第二行; 因为倒数第一行是$, $-1就是倒数第二行
5. #,# 选定范围,从第#起, 到第#行止; 2,5就是第二行到第五行;配合后续命令使用,
比如, 删除从第2行到第5行的数据就是, :2,5d
:10,20y,就是复制从第10行到第20行数据
复制后可以移动光标到某一行,然后输入p键, 则把复制内容粘贴到该行的下一行.
即使粘贴时, 光标不在行首也没关系, 因为会复制到下一行,而不是从光标当前位置开始插入
6. #,+# 从第#行开始起, 向下取#行, 2,+3 就是从第二行开始向下取3行, 也就是第2到5行
7. .,$-1 从当前行到倒数第二行; .,$-#, 从当前行到倒数第#+1行
8. % 表示全文, 相当于 1,$
1.3.2.2 地址定界后跟一个编辑命令
d #删除, 相当于剪切
y #复制
w file #将范围内的行另存至指定文件中 1,2w /opt/passwd.txt
r file #在指定行的下一行插入指定文件中的所有内容 1r /opt/passwd.txt
1.3.3 查找并替换
格式:
搜索范围s/要查找的内容/替换为的内容/修饰符
说明:
要查找的内容: 可使用基本正则表达式模式
替换为的内容: 不能使用模式, 但可以使用\1, \2, ...等后向引用符号; 还可以使用"&"引用前面查找时查找到的整个内容
范例: 搜索/etc/password中的root账号, 替换为admin
- 不加修饰符, 默认情况会查找范围内全部匹配到的数据, 但是每一行只会替换第一个匹配到的字符
:%s/root/admin/ # %为全文搜索
- 通过修饰符g, 替换范围内全部匹配到的数据
:%s/root/admin/g
- 通过修饰符i, 定义搜索时不区分大小写, 默认搜索是区分大小的.
:%s/admin/ROOT/ig
注意: 搜索是可以区分或者不区分大小写, 但是替换的内容一定是区分大小的, 替换成ADMIN就是改成ADMIN
查找替换中的分隔符/
可以替换为其他字符, @,#
范例:
s@@@
s###
1.3.4 定制vim的工作特性
扩展命令模式的配置只是对当前vim进程有效, 可将配置存放在文件中持久保存
配置文件:
/etc/vimrc 全局
~/.vimrc 个人
针对vim正在打开的文件临时生效:
范例: 用4个空格表示tab
切换到末行模式, 针对某个脚本设置
:set expandtab
:set 4
注意: 一旦关闭文件后, 临时的配置就会失效, 下次打开文件后, 需要再次设置
9. :set nu 显示行号
10. :set nonu 不显示行号
11. :set nohl 不高亮
12. 命令(普通)模式直接输入/, 进入搜索模式, 可以搜索关键字
1.3.4.1 行号
显示行号: set no
取消显示: set nonu
1.3.4.2 忽略字符的大小写
启用: set ic
不忽略: set noic
1.3.4.3 自动缩进
启用: set ai, 输入回车后, 下一行和上一行行首对齐
禁用: set noai
1.3.4.4 复制保留格式
启用: set paste, 使用了set ai后, 防止粘贴文本时串行, 出现格式混乱
禁用: set nopaste
1.3.4.5 显示Tab^|
和换行符$
启用: set list
禁用: set nolist
1.3.4.6 高亮搜索
启用: set hls
禁用: set nohl
1.3.4.7 语法高亮
启用: syn on
禁用: syn off
1.3.4.8 文件格式
启用Windows格式: set fileformat=dos
启用Unix格式; set fileformat=unix
简写 set ff=dos|unix, 将文本格式改为Windows/Unix
1.3.4.9 Tab用空格代替
不同的远程工具下, tab和空格数量的对应关系不同
启用: set expandtab 默认为8个空格代替Tab
禁用: set noexpandtab
1.3.4.10 Tab用指定空格的个数代替
启用: set tabstop=# 指定#个空格代替Tab
简写: set ts=4
1.3.4.11 设置光标所在行的标识线
启用: set cul
禁用: set nocursorline
1.3.4.12 帮助
set 帮助
:help option-list
:set or :set all
1.4 命令模式(普通模式)
行首行尾跳转
^: 跳转至行首的第一个非空白字符
0: 跳转至行首
$: 跳转至行尾
行间移动
# 扩展命令模式下: :行编号, :1表示第一行 :%最后一行
# 普通命令模式下: 行编号G, 1G或者gg表示第一行, G表示最后一行
替换命令
r: 只替换光标所在处的一个字符
R: 切换到REPLACE模式, 在末行会出现REPLACE提示, 按ESC回到命令模式
删除命令
d: 删除命令, 可结合光标跳转字符, 实现范围删除
d$: 删除光标当前到行尾, 或者用D
d^: 删除光标当前到非空行首
d0: 删除光标当前到行首
dd: 剪切光标所在行, 之后可以移动到目标处用p粘贴到光标下一行
数字dd: 删除从当前行开始的多行, 2dd表示从当前行开始, 删除两行, 包括当前行
dG: 从光标所在行开始往后, 删除整个文本
dgg: 从光标所在行开始往前, 删除整个文件
删除当前行尾的换行符
# 也就是把下面一行和当前行合并, 将光标移动到上面一行, 然后敲J
J
大小写转换
~
复制和粘贴
y: 复制
yy: 复制当前行, 相当于Y
y$: 从光标处复制到行尾
y0: 从光标处复制到行首
y^: 从光标处复制到非空行首
数字yy: 从当前行开始复制多行
P: 将复制的内容粘贴到光标所在行的上面
p: 将复制的内容粘贴到光标所在行的下面
查找
/模式: 从当前光标所在处向文本末尾查找
?模式: 从当前光标所在处向文本首部查找
n: 与命令同方向
N: 与命令反方向
撤销
u: 撤销最近的更改
数字u: 撤销之前几次更改
U: 撤销光标所在行此行的所有更改
ctrl+r: 重做最后一次撤销的更改
高级用法
- <起始位置><命令><结束为止>
常见命令: y复制, d删除, gU变大写, gu变小写
范例: 复制一行内容
0y$
0: 先定位到行首
y: 从行首开始赋值
$: 拷贝到本行的最后一个字符
范例: 粘贴"admin"100次
100iadmin[ESC]
命令模式执行
敲100, 表示粘贴100次
敲i, 进入插入模式
敲admin, 输入要粘贴的内容
敲ESC退出插入模式, 回到普通模式
- 针对一组特殊符号内的内容进行操作
范例: 删除一组特殊符号内的内容
di[
命令模式执行, 并且要将光标先移动到这组特殊符合内
d: 执行删除
i:
[: 表示删除的是一组[]内的全部内容
yi(
di"
di'
dtx: 从当前光标位开始删除, 直到遇到第一个字符x
ytx: 从当前光标位开始复制, 直到遇到第一个字符x
1.5 可视化模式
- 通过键盘光标选中要修改的字符/行或者矩形块, 然后进行内容操作
v: 面向字符, 在末行显示 -- VISUAL --, 可以按照字符进行选择, 然后执行命令, 比如删除或者复制
V: 面向整行, 在末行显示 -- VISUAL LINE --, 按照一整行去选择, 然后执行命令, 比如删除或者复制
ctrl+v: 面向块, 按照一个矩形块去选择, 在末行显示 -- VISUAL BLOCK --
范例: 在指定的列插入相同的内容
1. 将光标移动到要操作的行
2. ctrl+v, 进入可视化模式, 选择要操作的列和行
3. 输入I
4. 输入要插入的内容
5. 按ESC键
案例1: 在整个文件的行首, 插入#
gg, 先将光标移动到文件首行
ctrl+v, 进入块可视化模式
输入G, 这样可以选中每一行的第一个字符
输入I, 切换至插入模式, 这样可以在每一行的行首插入字符
输入#
ESC退出可视化模式
案例2: 删除每一行的第一个字符
gg, 先将光标移动到文件首行
ctrl+v
G
x
ESC
案例3: 在指定的列插入相同的内容
原理和插入#一样
ctrl+v
移动光标选中需要插入信息的列
输入I
输入内容
ESC
案例4: 复制/etc/rc.d/init.d/functions文件至/tmp目录. 替换/tmp/functions文件中的/etc/sysconfig/init为/var/log
:%s#/etc/sysconfig/init#/var/log#
案例5: 删除/tmp/functions文件中所有以#开头, 且#后面至少有一个空白字符的行的行首的#号
:%s@^#\( \+.*\)@\1@ # vim末行模式的搜索替换只支持基本正则表达式
2 文本常见处理工具
2.1 文本内容查看命令
2.1.1 查看文本文本内容
2.1.1.1 cat
cat 只能看文本文件, cat文件之前, 可以先通过file命令查看文本格式, 确定是否可以cat查看
[root@demo-c8 ~]# file /dev/urandom
/dev/urandom: character special (1/9)
[root@demo-c8 ~]# file /etc/fstab
/etc/fstab: ASCII text
格式:
cat [OPTION]... [FILE]...
常见选项:
-E 显示行结束符$
-A 显示所有控制符
-n 对显示出的每一行进行编号
-b 仅对非空行显示行号, 等于`nl`命令
-s 压缩连续的空行成一行
范例: cat -A查看Linux格式文件
# 准备测试文件
[root@demo-c8 ~]# cd /data
[root@demo-c8 data]# ls
[root@demo-c8 data]# vim f1.txt
a b
cc
d i v
-
cat -A: $:Linux的换行符
[root@demo-c8 data]# hexdump -C f1.txt # $符号就是0a换行
00000000 61 20 20 20 62 0a 63 63 0a 64 20 69 20 76 20 0a |a b.cc.d i v .|
00000010
范例: cat -A查看Windows格式文件
- cat -A: . ^M: Windows格式的回车符号, 也就是0d
[root@demo-c8 data]# hexdump -C a.txt
00000000 61 20 20 31 0d 0a 62 20 20 32 0d 0a 63 20 20 33 |a 1..b 2..c 3|
00000010
范例: cat多行重定向生成配置文件
cat > FILE_NAME <
>
EOF
- reset命令
恢复终端环境, 比如用cat打开了一些非文本文件后, 可能会执行一些乱码. 这时可能出现cat其他文本文件也是乱码的情况, 这时用reset命令恢复终端环境. 如果还不行, 可以断开SSH连接, 或者重启. 重启再不行,就排错吧. 所以不要用cat命令随便打开文件.
- tac命令
反向显示文本内容, 把第一行显示在最后一行, 和cat正好相反
- rev命令
反向显示文本内容, 把第一列显示在最后一列, 和cat正好相反
2.1.2 查看非文本文件内容
2.1.2.1 hexdump
- hexdump命令
有些文件是非文本文件, 可以用hexdump查看, 并且以指定的进制显示
格式:
hexdump [options] ...
Display file contents in hexadecimal, decimal, octal, or ascii.
一般用-C
选项以16进制显示, 比如hexdump -C -n 512 /dev/sda
, 查看sda硬盘前512字节
硬盘的前512个字节是非文本内容
范例: 将文本字符以ASCII码16进制显示
[root@demo-c8 ~]# echo abcd | hexdump -C
00000000 61 62 63 64 0a |abcd.|
00000005
2.2 分页查看文件内容
只要是支持标准输入的命令都可以用管道, 将前面命令的结果传给自己
more FILE
回车, 下一行
空格, 下一页
ctrl+d: 往回翻
q: 退出查看
缺点: 翻到了最后一页就自动退出, 不能再往回翻
less FILE
q: 退出查看
支持page up | page down翻页
翻到了最后一页不会自动退出
输入/可以搜索, n跳到下一个匹配, N跳到上一个匹配, 和vim中的搜索用法相同
2.3 显示文本前或后n行内容
head命令
默认显示文本前10行
-n数字 或者 -数字: 显示文本的前几行
-C数字: 显示文本的前几个字节
范例: head显示前n行
[root@demo-c8 ~]# seq 100 > text.txt
[root@demo-c8 ~]# head text.txt
1
2
3
4
5
6
7
8
9
10
范例: head显示前n个字节
# 数字和换行符各占一个字节
[root@demo-c8 ~]# head -c 10 text.txt
1 # 1和换行符
2
3
4
5
tr命令
-d 删除指定内容
-s 压缩, 将连续的指定内容压缩成一个字符
-c 取反, -dc就是除了后面匹配的内容, 都删除, 可以接通配符
面试题: 生成字符+数字随机密码
利用/dev/urandom文件, 该文件是字符块文件,生成随机信息, 不能用cat直接查看显示在屏幕上, 但是可以将cat结果通过管道传给tr命令, 然后把除了字符和数字的其他字符乱码都删除.这样就保留了随机的字符和数字
# /dev/random和/dev/urandom都是随机字符设备
0O8xmS]NKN[12:44:45 root@centos8-3 ~]#cat /dev/urandom | tr -dc '[:alnum:]' | head -c 10
mteifbL6l9[12:44:46 root@centos8-3 ~]#cat /dev/random | tr -dc '[:alnum:]' | head -c 10
GspCOBi05R[12:44:47 root@centos8-3 ~]#
tail命令
范例: 显示ifconfig
命令的第二行
[root@demo-c8 ~]# ifconfig | head -n2 | tail -1
inet 10.0.0.108 netmask 255.255.255.0 broadcast 10.0.0.255
tail -f: 跟踪文件变化, 常用于跟踪日志跟踪
tail -f: 默认显示现有日志的最后十行, 从倒数第十行开始, 显示到最新一行, 并且持续追踪新发生的日志, 新发生的日志会追加显示
-f: 追踪文件描述符, fd, 即使文件被删除, 也会持续追踪, 因为文件被删除后, 文件描述符不会被删除
-F: 追踪文件名称, 当文件被删除后, 追踪停止, 如果新建了一个同名文件, 那么会重新追踪
2.4 按列抽取文本cut
cut命令
当分隔符连续出现时, 比如df
命令的结果, 如果用cut
指定分隔符为空格时, 连续的空格也会被算作一列, 此时要用tr -s
先压缩空格
格式:
cut [option]... [FILE]...
选项:
-d DELIMITER: 指明分隔符,默认tab
-f FIElDS:
#: 第#个字段,例如:3, 表示仅取第三个字段
#,#[,#]:离散的多个字段,例如:1,3,6
#-#:连续的多个字段, 例如:1-6
混合使用:1-3,7
-c 按字符切割显示
--output-delimiter=STRING指定输出分隔符, 比如按:为分隔符切割, 按照;为分隔符显示
[root@demo-c8 ~]# cut -d: -f1 /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
games
ftp
nobody
dbus
systemd-coredump
systemd-resolve
tss
polkitd
geoclue
rtkit
...
[root@demo-c8 ~]# cut -d: -f1,3 /etc/passwd
root:0
bin:1
daemon:2
adm:3
lp:4
sync:5
shutdown:6
halt:7
mail:8
operator:11
games:12
ftp:14
...
[root@demo-c8 ~]# cut -d: --output-delimiter=";" -f1,3 /etc/passwd
root;0
bin;1
daemon;2
adm;3
lp;4
sync;5
shutdown;6
halt;7
mail;8
operator;11
games;12
...
范例: 显示磁盘使用率, 按由大到小显示
[root@demo-c8 ~]# df
Filesystem 1K-blocks Used Available Use% Mounted on
devtmpfs 3957252 0 3957252 0% /dev
tmpfs 3985420 0 3985420 0% /dev/shm
tmpfs 3985420 9832 3975588 1% /run
tmpfs 3985420 0 3985420 0% /sys/fs/cgroup
/dev/sda2 41922560 4542680 37379880 11% /
/dev/sda5 41922560 325336 41597224 1% /data
/dev/sda1 999320 192552 737956 21% /boot
tmpfs 797084 1168 795916 1% /run/user/42
tmpfs 797084 4 797080 1% /run/user/0
[root@demo-c8 ~]# df | tr -s " " | cut -d " " -f1,5 | tac | sort -k2 -r
Filesystem Use%
/dev/sda1 21%
/dev/sda2 11%
tmpfs 1%
tmpfs 1%
tmpfs 1%
/dev/sda5 1%
tmpfs 0%
tmpfs 0%
devtmpfs 0%
范例: 取本机ip地址
[root@demo-c8 ~]# ifconfig
ens160: flags=4163 mtu 1500
inet 10.0.0.108 netmask 255.255.255.0 broadcast 10.0.0.255
inet6 fe80::20c:29ff:fe97:37c8 prefixlen 64 scopeid 0x20
ether 00:0c:29:97:37:c8 txqueuelen 1000 (Ethernet)
RX packets 45571 bytes 31757064 (30.2 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 31525 bytes 3744162 (3.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73 mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 1000 (Local Loopback)
RX packets 48 bytes 4080 (3.9 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 48 bytes 4080 (3.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
virbr0: flags=4099 mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
ether 52:54:00:86:db:73 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@demo-c8 ~]# ifconfig | head -2 | tail -1
inet 10.0.0.108 netmask 255.255.255.0 broadcast 10.0.0.255
[root@demo-c8 ~]# ifconfig | head -2 | tail -1 | tr -s " " | cut -d" " -f3
10.0.0.108
2.5 合并多个文本paste
paste合并多个文件里相同行号的列到同一行
格式:
paste [OPTION]... [FILE]...
常用选项:
-d 分隔符: 指定分隔符, 默认为tab
-s: 所有行合成一行显示, 默认分隔符为tab
范例: 合并a.txt和b.txt
[root@demo-c8 ~]# vim a.txt
a
b
c
[root@demo-c8 ~]# vim b.txt
1
2
3
paste: 矩阵转置, 将文件的列转为行, 默认分隔符为tab
用ls
显示目录内文件时, 虽然是横向显示, 但是实际是纵向显示每个文件的. 也可用ls -1
来查看
[13:06:59 root@centos8-3 ~]#ls
anaconda-ks.cfg a.txt b.txt
[13:07:01 root@centos8-3 ~]#ls -1
anaconda-ks.cfg
a.txt
b.txt
2.6 分析文本的工具
2.6.1 收集文本统计数据wc
wc
命令可以用来统计文件的行总数, 单词总数, 字节总数和字符总数
可以对文件或者STDIN标准输入中的数据进行统计
常用选项:
-l 只统计行数
-w 只统计单词总数. wc统计文本单词个数, 是以空格来区分单词的
-c 只统计字节总数
-m 只统计字符总数
-L 显示文件中最长行的长度
范例: 可以用ls | wc -l
. 判断目录里有几个文件. 如果需要统计隐藏文件就用ls -a
[13:07:46 root@centos8-3 ~]#ls
anaconda-ks.cfg a.txt b.txt
[13:07:49 root@centos8-3 ~]#ls | wc -l
3
范例: wc -L
: 显示文本中, 最长一行的字符数
[root@demo-c8 ~]# cat /etc/passwd
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
[root@demo-c8 ~]# wc -L /etc/passwd
99 /etc/passwd
范例: wc FILE
[root@demo-c8 ~]# wc /etc/passwd
52 120 2901 /etc/passwd
文本行数 文本单词数 文本字节数
[root@demo-c8 ~]# ll /etc/passwd
-rw-r--r--. 1 root root 2901 Sep 5 15:45 /etc/passwd
2.6.2 文本排序sort
sort把整理过的文本显示在标准输出上, 并不改变原始文件
格式:
sort [OPTIONS] FILE(s)
常用选项:
-r 执行反方向(由上至下)整理
-R 随机排序
-n 执行按数字大小整理
-f 忽略(fold)字符串中的字符大小写
-u 选项(独特,unique),合并重复项,即去重
-t c 使用c做为字段界定符, 也就是指定分隔符, 默认按照空格分隔
-k # 按照第几列来排序
范例: 取出uid最大的前三行, 只显示用户名和uid
[root@demo-c8 ~]# cp /etc/passwd .
[root@demo-c8 ~]# cut -d: -f1,3 passwd | sort -t: -k2 -nr | head -3
nobody:65534
heiheiheihei:1004
heiheihei:1003
范例: 统计一共有多少个主机ip访问了nginx服务器
cut -d" " -f1 /var/log/nginx/access_log | sort -u | wc -l
范例: 统计每个ip访问了多少次
# 第一个sort是为了把所有的ip地址, 按照顺序进行排序, 这样相同的ip就会连续出现, 便于uniq做去重, 因为uniq只有在相邻的两行是相同的内容时才会去重
# uniq -c, 对ip地址进行去重, 并且显示每个ip地址出现的次数
# sort -k1 -nr, 按照第一列, 也就是相同ip出现的次数排序, 并且按照数字大小, 从大到小排序
[root@demo-c8 ~]# cut -d" " -f1 access_log | sort | uniq -c | sort -k1 -nr
4870 172.20.116.228
3429 172.20.116.208
2834 172.20.0.222
2613 172.20.112.14
2267 172.20.0.227
2262 172.20.116.179
2259 172.20.65.65
范例: 按照/etc/passwd中的uid字段把文本进行排序
[13:13:46 root@centos8-3 /data/prac]#sort -t: -k 3 -n /etc/passwd
-t: 指定分隔符为冒号, 指定第几列, 要定义分隔符
-k 数字: 指定第几列
-n: 如果指定的列都是数字, 想要按照数字大小排序, 需要-n, 默认是按照ASCII码顺序, 从左到右,012...9AaBb...Zz, 从左到右比较每一位
范例: 对用户名和uid,按照uid大小排序
[13:20:31 root@centos8-3 /data/prac]#cut -d: -f1,3 /etc/passwd | sort -t: -k 2 -n
[13:48:59 root@centos8-3 /data/prac]#cut -d' ' -f1 access_log | sort -u | wc -l
201
sort -u: 去重
sort 默认就是从左到右, ASCII码顺序排序, 比较每一位, 012...9AaBb...Zz
2.6.3 去重uniq
如果相邻的两行是相同的, 那么uniq才会去重, 所以uniq只会对相邻的两行, 并且两行内容相同的情况下, 才会去重
uniq -c 显示重复的个数, 在每行显示
[13:52:09 root@centos8-3 /data/prac]#cut -d' ' -f1 access_log | sort | uniq -c | sort -nr | head -1
4870 172.20.116.228
uniq -d 只显示相邻的重复的数据
uniq -u 只显示没有相邻重复的
范例: lastb
命令查看日志, 并且统计
- lastb显示失败的登录记录, 包含ip等
[14:08:31 root@centos8-3 /data/prac]#lastb -f btmp-34 | tr -s ' ' | cut -d ' ' -f3 | sort | uniq -c | sort -nr | head -10
86294 58.218.92.37
43148 58.218.92.26
18036 112.85.42.201
10501 111.26.195.101
10501 111.231.235.49
10501 111.204.186.207
10501 111.11.29.199
10499 118.26.23.225
6288 42.7.26.142
4236 58.218.92.30
面试题: 取两个文件, 相同和不同的行? 两个文件, 对应的行, 哪些是相同的哪些是不同的
先通过cat打开两个文件, 然后用sort排序, 默认按照ASCII码顺序, 把相同的行排列到相邻的位置, 再用uniq去重, -d会显示相同的行, -u显示不相同的行
cat FILE1 FILE2 | sort | uniq -d
cat FILE1 FILE2 | sort | uniq -u
[root@demo-c8 ~]# cat a.txt
a
b
1
2
c
[root@demo-c8 ~]# cat b.txt
1
2
3
# 相同的行
[root@demo-c8 ~]# cat a.txt b.txt | sort | uniq -d
1
2
# 不同的行
[root@demo-c8 ~]# cat a.txt b.txt | sort | uniq -u
3
a
b
c
2.6.4 比较文件
2.6.4.1 diff
diff命令可用于比较两个文件之间的区别, diff命令的输出可被保存在一种叫做补丁的文件中
常用选项:
diff FILE1 FILE2
-u 详细的显示两个文件的不同
范例: 比较a.txt和b.txt两个文件的不同
[root@demo-c8 ~]# cat a.txt
a
b
1
2
c
[root@demo-c8 ~]# cat b.txt
1
2
3
[root@demo-c8 ~]# diff a.txt b.txt
1,2d0
< a
< b
5c3
< c
---
> 3
# -u选项会以后面的文件为基准, 逐行进行比较
[root@demo-c8 ~]# diff -u a.txt b.txt
--- a.txt 2022-09-05 18:20:03.792540321 +0800 # -代表a.txt内容
+++ b.txt 2022-09-05 16:18:21.047676537 +0800 # +代表b.txt内容
@@ -1,5 +1,3 @@
-a # 比较第一行, 第一个文件需要把第一行a删除, 才能和第二个文件一致
-b # 比较第二行, 第一个文件需要把第二行b删除, 才能和第二个文件一致
1 # 第一个文件的a和b删除后, 两个文件的第一行就是一致的了, 为1
2 # 第一个文件的a和b删除后, 两个文件的第二行就是一致的了, 为2
-c # 第一个文件的第五行c需要被删除, 才能和第二个文件一致
+3 # 第一个文件需要加一行3, 才能和第二个文件一致
2.6.4.2 patch
diff命令的结果可以通过重定向输出到一个文本文件里, 基于这个文件, 可以用第一个文件还原出第二个文件
patch命令需要谨慎使用, 因为默认情况下, patch命令会丢失第一个文件
范例: 将a.txt和b.txt的diff结果输出到文本中, 通过a.txt和diff结果, 还原出b.txt
[root@demo-c8 ~]# diff -u a.txt b.txt > diff.log
[root@demo-c8 ~]# rm -rf b.txt
# 默认情况下, patch会把还原回来的文件命名成a.txt, 需要用-b选项, 先把a.txt进行备份
[root@demo-c8 ~]# patch -b a.txt diff.log # -b会把a.txt先进行备份
patching file a.txt
[root@demo-c8 ~]# cat a.txt # 此时, 新生成的a.txt为原来的b.txt
1
2
3
[root@demo-c8 ~]# cat a.txt.orig # .orig为备份的原来的a.txt
a
b
1
2
c
练习
1、找出ifconfig “网卡名” 命令结果中本机的IPv4地址
[root@demo-c8 ~]# ifconfig | head -2 | tail -1 | tr -s ' ' | cut -d" " -f3
10.0.0.108
2、查出分区空间使用率的最大百分比值
[root@demo-c8 ~]# df | tr -s " " | cut -d " " -f1,5 | tac | sort -k2 -r
Filesystem Use%
/dev/sda1 21%
/dev/sda2 12%
tmpfs 1%
tmpfs 1%
tmpfs 1%
/dev/sda5 1%
tmpfs 0%
tmpfs 0%
devtmpfs 0%
[root@demo-c8 ~]# df | tr -s " " %| cut -d "%" -f5 | tr -d "[:alpha:]" | sort -nr
21
12
1
1
1
1
0
0
0
[root@demo-c8 ~]#
3、查出用户UID最大值的用户名、UID及shell类型
[root@demo-c8 ~]# cut -d":" -f1,3,7 /etc/passwd | sort -t":" -k2 -nr | head -1
nobody:65534:/sbin/nologin
4、查出/tmp的权限,以数字方式显示
[root@demo-c8 ~]# stat /tmp
File: /tmp
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 802h/2050d Inode: 33555360 Links: 10
Access: (1777/drwxrwxrwt) Uid: ( 0/ root) Gid: ( 0/ root)
Context: system_u:object_r:tmp_t:s0
Access: 2022-09-05 14:41:10.010785301 +0800
Modify: 2022-09-05 19:03:01.535492239 +0800
Change: 2022-09-05 19:03:01.535492239 +0800
Birth: -
[root@demo-c8 ~]# stat /tmp | head -4 | tail -1 | cut -d " " -f2 | cut -d "/" -f1 | tr -dc "[:alnum:]"
1777[root@demo-c8 ~]#
5、统计当前连接本机的每个远程主机IP的连接数,并按从大到小排序
[root@demo-c8 ~]# ss -nt
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 52 10.0.0.108:22 10.0.0.1:54263
[root@demo-c8 ~]# ss -nt | grep "^ESTAB" | tr -s " " | cut -d" " -f5 | sort | uniq -c | sort -nr
1 10.0.0.1:54263