5: 文本處理工具

1. 文本編輯工具vim

1.1 vim介紹

在Linux中我們經(jīng)常編輯修改文本文件, 即由ASCII, Unicode或其他編碼的純文字的文件. Vim是一款使用最多的Linux平臺(tái)的文本編輯工具

vim安裝:

# 最小化安裝的系統(tǒng), 需要單獨(dú)安裝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...

常用選項(xiàng):

vim打開文件, 光標(biāo)默認(rèn)處在第一行行首
+#  打開文件后,讓光標(biāo)處于第#行的行首,`vim + FILE`: 打開文件后, 光標(biāo)處于最后一行行首. 
+/PATTERN   讓光標(biāo)處于第一個(gè)被PATTERN匹配到的行的行首
-b file 二進(jìn)制方式打開文件
-d file1 file2...  比較多個(gè)文件,相當(dāng)于 vimdiff
-m file    只讀打開文件
-e file    直接進(jìn)入ex模式,相當(dāng)于執(zhí)行ex  file 
-y file    Easy mode (like "evim", modeless),直接可以操作文件,ctrl+o:wq|q! 保存和不保存退出

說明:

  • 如果該文件存在,文件被打開并顯示內(nèi)容
  • 如果該文件不存在,當(dāng)編輯后第一次存盤時(shí)創(chuàng)建它

1.2.2 三種主要模式和轉(zhuǎn)換

vim 是一個(gè)模式編輯器,其行為是依賴于 vim的模式

三種常見模式:

  • 命令或普通(Normal)模式:默認(rèn)模式,可以實(shí)現(xiàn)移動(dòng)光標(biāo),剪切/粘貼文本
  • 插入(Insert)或編輯模式:用于修改文本
  • 擴(kuò)展命令(extended command )或命令(末)行模式:保存,退出等

模式轉(zhuǎn)換

  • 命令模式 --> 插入模式
i      insert, 在光標(biāo)所在處輸入
I      在當(dāng)前光標(biāo)所在行的行首輸入
a      在當(dāng)前光標(biāo)所在處后面輸入
A      在當(dāng)前光標(biāo)所在行行尾輸入
o      在當(dāng)前光標(biāo)所在行的下方打開一個(gè)新行
O      在當(dāng)前光標(biāo)所在行的上方打開一個(gè)新行
行首插入: I
行尾插入: A
上一行插入: O
下一行插入: o
光標(biāo)處插入: i
光標(biāo)處下一位插入: a
  • 插入模式 -- ESC -- 命令模式
  • 命令模式 -- : -- 擴(kuò)展命令模式
  • 擴(kuò)展命令模式 -- ESC -- 命令模式

1.3 擴(kuò)展命令模式

按冒號(hào) " : " 可以進(jìn)入Ex模式,創(chuàng)建一個(gè)命令提示符: 處于底部的屏幕左側(cè)

1.3.1 擴(kuò)展命令模式基本命令

w                           寫(存)磁盤文件
wq                          寫入并退出
x                           寫入并退出
X                           加密
q                           退出
q!                         不存盤退出,未保存更改都將丟失
r   filename                讀取文件內(nèi)容到當(dāng)前文件中, 在光標(biāo)所在行下一行插入
范例: :r/data/prac/test.txt, 如果讀取的是和當(dāng)前文件在同一個(gè)目錄的文件, 要使用./文件名

w   filename                將當(dāng)前文件內(nèi)容寫入另一個(gè)文件
范例: :w/data/prac/test.txt, 如果寫入的是和當(dāng)前文件在同一個(gè)目錄的文件, 要使用./文件名. 如果目標(biāo)文件不存在, 會(huì)自動(dòng)創(chuàng)建文件, 并寫入內(nèi)容
                             如果目標(biāo)文件存在, 那么就要加!,去覆蓋掉原文件內(nèi)容, :w!./f1.txt

!command                    執(zhí)行命令, 打印在屏幕上,但是不會(huì)追加到文件中
r!command                   讀取命令的輸出. 將命令的輸出追加到鼠標(biāo)當(dāng)前行的下一行

1.3.2 地址定界

在末行模式執(zhí)行

格式:

地址界定后需要接命令, 來完成操作
:start_pos,end_pos CMD

1.3.2.1 地址定界格式

在末行模式輸入以下格式

1. #          將光標(biāo)移動(dòng)到第幾行的行首, :2就是移動(dòng)到第二行行首
2. .          將光標(biāo)移動(dòng)到當(dāng)前行的行首
3. $          將光標(biāo)移動(dòng)到最后一行行首, %也是移動(dòng)到最后一行行首
4. $-#        將光標(biāo)移動(dòng)到倒數(shù)第#+1行, $-1就是倒數(shù)第二行; 因?yàn)榈箶?shù)第一行是$, $-1就是倒數(shù)第二行
5. #,#        選定范圍,從第#起, 到第#行止; 2,5就是第二行到第五行;配合后續(xù)命令使用,
比如, 刪除從第2行到第5行的數(shù)據(jù)就是, :2,5d
      :10,20y,就是復(fù)制從第10行到第20行數(shù)據(jù)
      復(fù)制后可以移動(dòng)光標(biāo)到某一行,然后輸入p鍵, 則把復(fù)制內(nèi)容粘貼到該行的下一行. 
      即使粘貼時(shí), 光標(biāo)不在行首也沒關(guān)系, 因?yàn)闀?huì)復(fù)制到下一行,而不是從光標(biāo)當(dāng)前位置開始插入

6. #,+#       從第#行開始起, 向下取#行, 2,+3 就是從第二行開始向下取3行, 也就是第2到5行
7. .,$-1      從當(dāng)前行到倒數(shù)第二行; .,$-#, 從當(dāng)前行到倒數(shù)第#+1行
8. %          表示全文, 相當(dāng)于 1,$ 

1.3.2.2 地址定界后跟一個(gè)編輯命令

d           #刪除, 相當(dāng)于剪切
y           #復(fù)制
w file      #將范圍內(nèi)的行另存至指定文件中  1,2w /opt/passwd.txt
r file     #在指定行的下一行插入指定文件中的所有內(nèi)容 1r /opt/passwd.txt

1.3.3 查找并替換

格式:

搜索范圍s/要查找的內(nèi)容/替換為的內(nèi)容/修飾符

說明:

要查找的內(nèi)容: 可使用基本正則表達(dá)式模式
替換為的內(nèi)容: 不能使用模式, 但可以使用\1, \2, ...等后向引用符號(hào); 還可以使用"&"引用前面查找時(shí)查找到的整個(gè)內(nèi)容

范例: 搜索/etc/password中的root賬號(hào), 替換為admin

  1. 不加修飾符, 默認(rèn)情況會(huì)查找范圍內(nèi)全部匹配到的數(shù)據(jù), 但是每一行只會(huì)替換第一個(gè)匹配到的字符
:%s/root/admin/    # %為全文搜索
  1. 通過修飾符g, 替換范圍內(nèi)全部匹配到的數(shù)據(jù)
:%s/root/admin/g
  1. 通過修飾符i, 定義搜索時(shí)不區(qū)分大小寫, 默認(rèn)搜索是區(qū)分大小的.
:%s/admin/ROOT/ig

注意: 搜索是可以區(qū)分或者不區(qū)分大小寫, 但是替換的內(nèi)容一定是區(qū)分大小的, 替換成ADMIN就是改成ADMIN

查找替換中的分隔符/可以替換為其他字符, @,#

范例:

s@@@
s###

1.3.4 定制vim的工作特性

擴(kuò)展命令模式的配置只是對(duì)當(dāng)前vim進(jìn)程有效, 可將配置存放在文件中持久保存

配置文件:

/etc/vimrc 全局
~/.vimrc  個(gè)人

針對(duì)vim正在打開的文件臨時(shí)生效:

范例: 用4個(gè)空格表示tab

切換到末行模式, 針對(duì)某個(gè)腳本設(shè)置
:set expandtab
:set 4

注意: 一旦關(guān)閉文件后, 臨時(shí)的配置就會(huì)失效, 下次打開文件后, 需要再次設(shè)置

9. :set nu    顯示行號(hào)
10. :set nonu  不顯示行號(hào)
11. :set nohl   不高亮
12. 命令(普通)模式直接輸入/, 進(jìn)入搜索模式, 可以搜索關(guān)鍵字

1.3.4.1 行號(hào)

顯示行號(hào): set no
取消顯示: set nonu

1.3.4.2 忽略字符的大小寫

啟用: set ic
不忽略: set noic

1.3.4.3 自動(dòng)縮進(jìn)

啟用: set ai, 輸入回車后, 下一行和上一行行首對(duì)齊
禁用: set noai

1.3.4.4 復(fù)制保留格式

啟用: set paste, 使用了set ai后, 防止粘貼文本時(shí)串行, 出現(xiàn)格式混亂
禁用: 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
簡(jiǎn)寫 set ff=dos|unix, 將文本格式改為Windows/Unix

1.3.4.9 Tab用空格代替

不同的遠(yuǎn)程工具下, tab和空格數(shù)量的對(duì)應(yīng)關(guān)系不同
啟用: set expandtab 默認(rèn)為8個(gè)空格代替Tab
禁用: set noexpandtab

1.3.4.10 Tab用指定空格的個(gè)數(shù)代替

啟用: set tabstop=# 指定#個(gè)空格代替Tab
簡(jiǎn)寫: set ts=4

1.3.4.11 設(shè)置光標(biāo)所在行的標(biāo)識(shí)線

啟用: set cul
禁用: set nocursorline

1.3.4.12 幫助

set 幫助

:help option-list
:set or :set all

1.4 命令模式(普通模式)

行首行尾跳轉(zhuǎn)

^: 跳轉(zhuǎn)至行首的第一個(gè)非空白字符
0: 跳轉(zhuǎn)至行首
$: 跳轉(zhuǎn)至行尾

行間移動(dòng)

# 擴(kuò)展命令模式下: :行編號(hào), :1表示第一行 :%最后一行
# 普通命令模式下: 行編號(hào)G, 1G或者gg表示第一行, G表示最后一行

替換命令

r: 只替換光標(biāo)所在處的一個(gè)字符
R: 切換到REPLACE模式, 在末行會(huì)出現(xiàn)REPLACE提示, 按ESC回到命令模式

刪除命令

d: 刪除命令, 可結(jié)合光標(biāo)跳轉(zhuǎn)字符, 實(shí)現(xiàn)范圍刪除
d$: 刪除光標(biāo)當(dāng)前到行尾, 或者用D
d^: 刪除光標(biāo)當(dāng)前到非空行首
d0: 刪除光標(biāo)當(dāng)前到行首
dd: 剪切光標(biāo)所在行, 之后可以移動(dòng)到目標(biāo)處用p粘貼到光標(biāo)下一行
數(shù)字dd: 刪除從當(dāng)前行開始的多行, 2dd表示從當(dāng)前行開始, 刪除兩行, 包括當(dāng)前行
dG: 從光標(biāo)所在行開始往后, 刪除整個(gè)文本
dgg: 從光標(biāo)所在行開始往前, 刪除整個(gè)文件 

刪除當(dāng)前行尾的換行符

# 也就是把下面一行和當(dāng)前行合并, 將光標(biāo)移動(dòng)到上面一行, 然后敲J
J

大小寫轉(zhuǎn)換

~

復(fù)制和粘貼

y: 復(fù)制
yy: 復(fù)制當(dāng)前行, 相當(dāng)于Y
y$: 從光標(biāo)處復(fù)制到行尾
y0: 從光標(biāo)處復(fù)制到行首
y^: 從光標(biāo)處復(fù)制到非空行首
數(shù)字yy: 從當(dāng)前行開始復(fù)制多行
P: 將復(fù)制的內(nèi)容粘貼到光標(biāo)所在行的上面
p: 將復(fù)制的內(nèi)容粘貼到光標(biāo)所在行的下面

查找

/模式: 從當(dāng)前光標(biāo)所在處向文本末尾查找
?模式: 從當(dāng)前光標(biāo)所在處向文本首部查找
n: 與命令同方向
N: 與命令反方向

撤銷

u: 撤銷最近的更改
數(shù)字u: 撤銷之前幾次更改
U: 撤銷光標(biāo)所在行此行的所有更改
ctrl+r: 重做最后一次撤銷的更改

高級(jí)用法

  • <起始位置><命令><結(jié)束為止>

常見命令: y復(fù)制, d刪除, gU變大寫, gu變小寫

范例: 復(fù)制一行內(nèi)容

0y$ 
0: 先定位到行首
y: 從行首開始賦值
$: 拷貝到本行的最后一個(gè)字符

范例: 粘貼"admin"100次

100iadmin[ESC]

命令模式執(zhí)行

敲100, 表示粘貼100次
敲i, 進(jìn)入插入模式
敲admin, 輸入要粘貼的內(nèi)容
敲ESC退出插入模式, 回到普通模式
  • 針對(duì)一組特殊符號(hào)內(nèi)的內(nèi)容進(jìn)行操作

范例: 刪除一組特殊符號(hào)內(nèi)的內(nèi)容

di[

命令模式執(zhí)行, 并且要將光標(biāo)先移動(dòng)到這組特殊符合內(nèi)

d: 執(zhí)行刪除
i: 
[: 表示刪除的是一組[]內(nèi)的全部?jī)?nèi)容
yi(
di"
di'
dtx: 從當(dāng)前光標(biāo)位開始刪除, 直到遇到第一個(gè)字符x
ytx: 從當(dāng)前光標(biāo)位開始復(fù)制, 直到遇到第一個(gè)字符x

1.5 可視化模式

  • 通過鍵盤光標(biāo)選中要修改的字符/行或者矩形塊, 然后進(jìn)行內(nèi)容操作
v: 面向字符, 在末行顯示 -- VISUAL --, 可以按照字符進(jìn)行選擇, 然后執(zhí)行命令, 比如刪除或者復(fù)制
V: 面向整行, 在末行顯示 -- VISUAL LINE --, 按照一整行去選擇, 然后執(zhí)行命令, 比如刪除或者復(fù)制
ctrl+v: 面向塊, 按照一個(gè)矩形塊去選擇, 在末行顯示 --  VISUAL BLOCK --

范例: 在指定的列插入相同的內(nèi)容

1. 將光標(biāo)移動(dòng)到要操作的行
2. ctrl+v, 進(jìn)入可視化模式, 選擇要操作的列和行
3. 輸入I
4. 輸入要插入的內(nèi)容
5. 按ESC鍵

案例1: 在整個(gè)文件的行首, 插入#

gg, 先將光標(biāo)移動(dòng)到文件首行
ctrl+v, 進(jìn)入塊可視化模式
輸入G, 這樣可以選中每一行的第一個(gè)字符
輸入I, 切換至插入模式, 這樣可以在每一行的行首插入字符
輸入#
ESC退出可視化模式

案例2: 刪除每一行的第一個(gè)字符

gg, 先將光標(biāo)移動(dòng)到文件首行
ctrl+v
G
x
ESC

案例3: 在指定的列插入相同的內(nèi)容

原理和插入#一樣
ctrl+v
移動(dòng)光標(biāo)選中需要插入信息的列
輸入I
輸入內(nèi)容
ESC

案例4: 復(fù)制/etc/rc.d/init.d/functions文件至/tmp目錄. 替換/tmp/functions文件中的/etc/sysconfig/init為/var/log

:%s#/etc/sysconfig/init#/var/log#

案例5: 刪除/tmp/functions文件中所有以#開頭, 且#后面至少有一個(gè)空白字符的行的行首的#號(hào)

:%s@^#\( \+.*\)@\1@ # vim末行模式的搜索替換只支持基本正則表達(dá)式

2 文本常見處理工具

2.1 文本內(nèi)容查看命令

2.1.1 查看文本文本內(nèi)容

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

常見選項(xiàng):

-E 顯示行結(jié)束符$
-A 顯示所有控制符
-n 對(duì)顯示出的每一行進(jìn)行編號(hào)
-b 僅對(duì)非空行顯示行號(hào), 等于`nl`命令
-s 壓縮連續(xù)的空行成一行

范例: cat -A查看Linux格式文件

# 準(zhǔn)備測(cè)試文件

[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的換行符


    image.png
[root@demo-c8 data]# hexdump -C f1.txt   # $符號(hào)就是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格式文件

image.png
  • cat -A: . ^M: Windows格式的回車符號(hào), 也就是0d
image.png
[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
>
>
EOF
  • reset命令

恢復(fù)終端環(huán)境, 比如用cat打開了一些非文本文件后, 可能會(huì)執(zhí)行一些亂碼. 這時(shí)可能出現(xiàn)cat其他文本文件也是亂碼的情況, 這時(shí)用reset命令恢復(fù)終端環(huán)境. 如果還不行, 可以斷開SSH連接, 或者重啟. 重啟再不行,就排錯(cuò)吧. 所以不要用cat命令隨便打開文件.

  • tac命令
反向顯示文本內(nèi)容, 把第一行顯示在最后一行, 和cat正好相反
  • rev命令
反向顯示文本內(nèi)容, 把第一列顯示在最后一列, 和cat正好相反

2.1.2 查看非文本文件內(nèi)容

2.1.2.1 hexdump

  • hexdump命令

有些文件是非文本文件, 可以用hexdump查看, 并且以指定的進(jìn)制顯示

格式:

hexdump [options] <file>...
Display file contents in hexadecimal, decimal, octal, or ascii.

一般用-C選項(xiàng)以16進(jìn)制顯示, 比如hexdump -C -n 512 /dev/sda, 查看sda硬盤前512字節(jié)

硬盤的前512個(gè)字節(jié)是非文本內(nèi)容

image.png

范例: 將文本字符以ASCII碼16進(jìn)制顯示

[root@demo-c8 ~]# echo abcd | hexdump -C 
00000000  61 62 63 64 0a                                    |abcd.|
00000005

2.2 分頁查看文件內(nèi)容

只要是支持標(biāo)準(zhǔn)輸入的命令都可以用管道, 將前面命令的結(jié)果傳給自己

more FILE

回車, 下一行
空格, 下一頁
ctrl+d: 往回翻
q: 退出查看

缺點(diǎn): 翻到了最后一頁就自動(dòng)退出, 不能再往回翻

less FILE

q: 退出查看
支持page up | page down翻頁 
翻到了最后一頁不會(huì)自動(dòng)退出
輸入/可以搜索, n跳到下一個(gè)匹配, N跳到上一個(gè)匹配, 和vim中的搜索用法相同

2.3 顯示文本前或后n行內(nèi)容

head命令

默認(rèn)顯示文本前10行
-n數(shù)字 或者 -數(shù)字: 顯示文本的前幾行
-C數(shù)字: 顯示文本的前幾個(gè)字節(jié)

范例: 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個(gè)字節(jié)

# 數(shù)字和換行符各占一個(gè)字節(jié)
[root@demo-c8 ~]# head -c 10 text.txt 
1 # 1和換行符
2
3
4
5

tr命令

-d 刪除指定內(nèi)容
-s 壓縮, 將連續(xù)的指定內(nèi)容壓縮成一個(gè)字符
-c 取反, -dc就是除了后面匹配的內(nèi)容, 都刪除, 可以接通配符

面試題: 生成字符+數(shù)字隨機(jī)密碼

利用/dev/urandom文件, 該文件是字符塊文件,生成隨機(jī)信息, 不能用cat直接查看顯示在屏幕上, 但是可以將cat結(jié)果通過管道傳給tr命令, 然后把除了字符和數(shù)字的其他字符亂碼都刪除.這樣就保留了隨機(jī)的字符和數(shù)字

# /dev/random和/dev/urandom都是隨機(jī)字符設(shè)備
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: 默認(rèn)顯示現(xiàn)有日志的最后十行, 從倒數(shù)第十行開始, 顯示到最新一行, 并且持續(xù)追蹤新發(fā)生的日志, 新發(fā)生的日志會(huì)追加顯示
-f: 追蹤文件描述符, fd, 即使文件被刪除, 也會(huì)持續(xù)追蹤, 因?yàn)槲募粍h除后, 文件描述符不會(huì)被刪除
-F: 追蹤文件名稱, 當(dāng)文件被刪除后, 追蹤停止, 如果新建了一個(gè)同名文件, 那么會(huì)重新追蹤

2.4 按列抽取文本cut

cut命令

當(dāng)分隔符連續(xù)出現(xiàn)時(shí), 比如df命令的結(jié)果, 如果用cut指定分隔符為空格時(shí), 連續(xù)的空格也會(huì)被算作一列, 此時(shí)要用tr -s先壓縮空格

格式:

cut [option]... [FILE]...

選項(xiàng):

-d DELIMITER: 指明分隔符,默認(rèn)tab
-f FIElDS:
     #: 第#個(gè)字段,例如:3, 表示僅取第三個(gè)字段
     #,#[,#]:離散的多個(gè)字段,例如:1,3,6
     #-#:連續(xù)的多個(gè)字段, 例如: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%

范例: 取本機(jī)ip地址

[root@demo-c8 ~]# ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  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<link>
        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<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        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<UP,BROADCAST,MULTICAST>  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 合并多個(gè)文本paste

paste合并多個(gè)文件里相同行號(hào)的列到同一行

格式:

paste [OPTION]... [FILE]...

常用選項(xiàng):

-d 分隔符: 指定分隔符, 默認(rèn)為tab
-s: 所有行合成一行顯示, 默認(rèn)分隔符為tab

范例: 合并a.txt和b.txt

[root@demo-c8 ~]# vim a.txt
a
b
c

[root@demo-c8 ~]# vim b.txt
1
2
3
image.png
image.png
image.png
image.png

paste: 矩陣轉(zhuǎn)置, 將文件的列轉(zhuǎn)為行, 默認(rèn)分隔符為tab

image.png

ls顯示目錄內(nèi)文件時(shí), 雖然是橫向顯示, 但是實(shí)際是縱向顯示每個(gè)文件的. 也可用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 收集文本統(tǒng)計(jì)數(shù)據(jù)wc

wc命令可以用來統(tǒng)計(jì)文件的行總數(shù), 單詞總數(shù), 字節(jié)總數(shù)和字符總數(shù)

可以對(duì)文件或者STDIN標(biāo)準(zhǔn)輸入中的數(shù)據(jù)進(jìn)行統(tǒng)計(jì)

常用選項(xiàng):

-l   只統(tǒng)計(jì)行數(shù)
-w   只統(tǒng)計(jì)單詞總數(shù). wc統(tǒng)計(jì)文本單詞個(gè)數(shù), 是以空格來區(qū)分單詞的
-c   只統(tǒng)計(jì)字節(jié)總數(shù)
-m   只統(tǒng)計(jì)字符總數(shù)
-L   顯示文件中最長(zhǎng)行的長(zhǎng)度

范例: 可以用ls | wc -l. 判斷目錄里有幾個(gè)文件. 如果需要統(tǒng)計(jì)隱藏文件就用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: 顯示文本中, 最長(zhǎng)一行的字符數(shù)

[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
文本行數(shù)   文本單詞數(shù)   文本字節(jié)數(shù)

[root@demo-c8 ~]# ll /etc/passwd
-rw-r--r--. 1 root root 2901 Sep  5 15:45 /etc/passwd

2.6.2 文本排序sort

sort把整理過的文本顯示在標(biāo)準(zhǔn)輸出上, 并不改變?cè)嘉募?/p>

格式:

sort [OPTIONS] FILE(s)

常用選項(xiàng):

-r 執(zhí)行反方向(由上至下)整理
-R 隨機(jī)排序
-n 執(zhí)行按數(shù)字大小整理
-f 忽略(fold)字符串中的字符大小寫
-u 選項(xiàng)(獨(dú)特,unique),合并重復(fù)項(xiàng),即去重
-t c 使用c做為字段界定符, 也就是指定分隔符, 默認(rèn)按照空格分隔
-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

范例: 統(tǒng)計(jì)一共有多少個(gè)主機(jī)ip訪問了nginx服務(wù)器

cut -d" " -f1 /var/log/nginx/access_log | sort -u | wc -l

范例: 統(tǒng)計(jì)每個(gè)ip訪問了多少次

# 第一個(gè)sort是為了把所有的ip地址, 按照順序進(jìn)行排序, 這樣相同的ip就會(huì)連續(xù)出現(xiàn), 便于uniq做去重, 因?yàn)閡niq只有在相鄰的兩行是相同的內(nèi)容時(shí)才會(huì)去重
# uniq -c, 對(duì)ip地址進(jìn)行去重, 并且顯示每個(gè)ip地址出現(xiàn)的次數(shù)
# sort -k1 -nr, 按照第一列, 也就是相同ip出現(xiàn)的次數(shù)排序, 并且按照數(shù)字大小, 從大到小排序
[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字段把文本進(jìn)行排序

[13:13:46 root@centos8-3 /data/prac]#sort -t: -k 3 -n /etc/passwd
-t:  指定分隔符為冒號(hào), 指定第幾列, 要定義分隔符
-k 數(shù)字: 指定第幾列
-n: 如果指定的列都是數(shù)字, 想要按照數(shù)字大小排序, 需要-n, 默認(rèn)是按照ASCII碼順序, 從左到右,012...9AaBb...Zz, 從左到右比較每一位

范例: 對(duì)用戶名和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 默認(rèn)就是從左到右, ASCII碼順序排序, 比較每一位, 012...9AaBb...Zz

2.6.3 去重uniq

如果相鄰的兩行是相同的, 那么uniq才會(huì)去重, 所以u(píng)niq只會(huì)對(duì)相鄰的兩行, 并且兩行內(nèi)容相同的情況下, 才會(huì)去重

uniq -c 顯示重復(fù)的個(gè)數(shù), 在每行顯示

[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 只顯示相鄰的重復(fù)的數(shù)據(jù)
uniq -u 只顯示沒有相鄰重復(fù)的

范例: lastb命令查看日志, 并且統(tǒng)計(jì)

  • 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

面試題: 取兩個(gè)文件, 相同和不同的行? 兩個(gè)文件, 對(duì)應(yīng)的行, 哪些是相同的哪些是不同的

先通過cat打開兩個(gè)文件, 然后用sort排序, 默認(rèn)按照ASCII碼順序, 把相同的行排列到相鄰的位置, 再用uniq去重, -d會(huì)顯示相同的行, -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命令可用于比較兩個(gè)文件之間的區(qū)別, diff命令的輸出可被保存在一種叫做補(bǔ)丁的文件中

常用選項(xiàng):

diff FILE1 FILE2 
-u 詳細(xì)的顯示兩個(gè)文件的不同

范例: 比較a.txt和b.txt兩個(gè)文件的不同

[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選項(xiàng)會(huì)以后面的文件為基準(zhǔn), 逐行進(jìn)行比較
[root@demo-c8 ~]# diff -u a.txt b.txt 
--- a.txt   2022-09-05 18:20:03.792540321 +0800  # -代表a.txt內(nèi)容
+++ b.txt   2022-09-05 16:18:21.047676537 +0800  # +代表b.txt內(nèi)容
@@ -1,5 +1,3 @@
-a    # 比較第一行, 第一個(gè)文件需要把第一行a刪除, 才能和第二個(gè)文件一致
-b    # 比較第二行, 第一個(gè)文件需要把第二行b刪除, 才能和第二個(gè)文件一致
 1    # 第一個(gè)文件的a和b刪除后, 兩個(gè)文件的第一行就是一致的了, 為1
 2    # 第一個(gè)文件的a和b刪除后, 兩個(gè)文件的第二行就是一致的了, 為2
-c   # 第一個(gè)文件的第五行c需要被刪除, 才能和第二個(gè)文件一致
+3  # 第一個(gè)文件需要加一行3, 才能和第二個(gè)文件一致

2.6.4.2 patch

diff命令的結(jié)果可以通過重定向輸出到一個(gè)文本文件里, 基于這個(gè)文件, 可以用第一個(gè)文件還原出第二個(gè)文件

patch命令需要謹(jǐn)慎使用, 因?yàn)槟J(rèn)情況下, patch命令會(huì)丟失第一個(gè)文件

范例: 將a.txt和b.txt的diff結(jié)果輸出到文本中, 通過a.txt和diff結(jié)果, 還原出b.txt

[root@demo-c8 ~]# diff -u a.txt b.txt > diff.log
[root@demo-c8 ~]# rm -rf b.txt 
# 默認(rèn)情況下, patch會(huì)把還原回來的文件命名成a.txt, 需要用-b選項(xiàng), 先把a(bǔ).txt進(jìn)行備份
[root@demo-c8 ~]# patch -b a.txt diff.log # -b會(huì)把a(bǔ).txt先進(jìn)行備份
patching file a.txt
[root@demo-c8 ~]# cat a.txt  # 此時(shí), 新生成的a.txt為原來的b.txt
1
2
3
[root@demo-c8 ~]# cat a.txt.orig  # .orig為備份的原來的a.txt
a
b
1
2
c

練習(xí)
1、找出ifconfig “網(wǎng)卡名” 命令結(jié)果中本機(jī)的IPv4地址

[root@demo-c8 ~]# ifconfig | head -2 | tail -1 | tr -s ' ' | cut -d" " -f3
10.0.0.108

2、查出分區(qū)空間使用率的最大百分比值

[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的權(quán)限,以數(shù)字方式顯示

[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、統(tǒng)計(jì)當(dāng)前連接本機(jī)的每個(gè)遠(yuǎn)程主機(jī)IP的連接數(shù),并按從大到小排序

[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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容