Linux運維:grep與sed命令

grep命令

grep全面搜索正則表達式並把行打印出來,是一種強大的文本搜索工具,它能使用正則表達式搜索文本,並把匹配的行打印出來。它的輸出通常是打印在屏幕上。python

Unix的grep家族包括grep、egrep和fgrep。egrep和fgrep的命令只跟grep有很小不一樣。egrep是grep的擴展,支持更多的re元字符, fgrep就是fixed grep或fast grep,它們把全部的字母都看做單詞,也就是說,正則表達式中的元字符表示回其自身的字面意義,再也不特殊。linux使用GNU版本的grep。它功能更強,能夠經過-G、-E、-F命令行選項來使用egrep和fgrep的功能。linux

grep如何工做的?

grep 命令在一個或多個文件中查找某個字符模式。若是這個模式中包含空格,就必須用引號把它括起來。 grep 命令中,模式能夠是一個被引號括括起來的字符串,也能夠是單個詞,位於模式以後全部的單詞都被視爲文件名。 grep 將輸出發送到屏幕,它不會對輸入文件進行任何修改或變化。
示例1:grep root /etc/passwd
說明:grep命令將在文件/etc/passwd中查找模式root。若是查找成功,文件中相應的行就會顯示在屏幕上,返回狀態爲0。若是查找失敗,就不會有任何輸出,返回狀態爲1。若是文件不存在,屏幕會顯示報錯信息,返回狀態爲2。正則表達式

$ grep root /etc/passwd123 # 文件不存在
grep: /etc/passwd123: 沒有那個文件或目錄
$ echo $?
2 # 狀態值爲2
$ grep lala /etc/passwd # 查找模式不匹配
$ echo $?
1 # 狀態值爲1
$ grep root /etc/passwd # 成功匹配
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
$ echo $?
0 # 狀態值爲0,成功匹配

grep命令的輸入能夠來自文件,也能夠來自標準輸入或者管道。
示例2:ps aux | grep dockerdocker

[root@moli-04 ~]# ps aux | grep docker
root        893  0.1  5.5 486428 55472 ?        Ssl  11:33   0:02 /usr/bin/dockerd
root        986  0.0  2.9 384508 29544 ?        Ssl  11:33   0:01 docker-containerd --config /var/run/docker/containerd/containerd.toml
root       1296  0.0  0.2 108964  2628 ?        Sl   11:33   0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5000 -container-ip 172.17.0.2 -container-port 5000
root       1301  0.0  0.2   7488  2676 ?        Sl   11:33   0:00 docker-containerd-shim -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/63683775af1b8dd27080dbf898619a3f50a17bf557ac0e133ab52310c84dbf5e -address /var/run/docker/containerd/docker-containerd.sock -containerd-binary /usr/bin/docker-containerd -runtime-root /var/run/docker/runtime-runc
root       1317  0.0  0.8  20272  8128 ?        Ssl  11:33   0:00 registry serve /etc/docker/registry/config.yml
root       1404  0.0  0.0 112720   968 pts/0    R+   12:00   0:00 grep --color=auto docker

ps aux命令的輸入被送到grep,而後包含docker的行都被輸出到屏幕上。shell

正則表達式

grep支持不少正則表達式元字符,以便用戶更精確地定義查找模式。
下面列出grep支持的經常使用基本表達式:bash

字符 含義
a 匹配字母a
. 匹配任意一個字符
* 匹配前一個字符出現0次或屢次
.* 匹配任意字符
[ ] 匹配集合中任意一個字符,括號中爲一個集合
[x-y] 匹配連續的字符串範圍
^ 匹配字符的開頭
$ 匹配字符的結尾
[^] 匹配否點,對括號中的集合取反
\ 匹配轉義後的字符串
\{n,m\} 匹配前一個字符出現n到m次
\{n,\} 匹配前一個字符至少出現n次
\{n\} 匹配前一個字符出現n次
() 保存已匹配的字符串,最大存儲9個,括號左右須要使用轉義字符(這裏不知道爲何顯示不了...)

grep命令的經常使用選項

選項 說明
-A num (A即after)顯示匹配的行,並顯示匹配行的後num行,num爲數字
-B num (B即before)除了顯示匹配的行,還顯示匹配行的前num行,num爲數字
-C num 先後匹配(至關於-A和-B)除了顯示匹配的行,還顯示匹配行的先後num行
-n 在輸出結果顯示行號,行號是該行在原來文件裏的行號,而不是輸出結果的行號
-v 取反,輸出與匹配模式相反的內容
-E 至關與egrep,後面的模式是擴展正則表達式(grep -E == egrep)
-o 只顯示匹配內容,grep默認輸出匹配內容的行,加上-o選項只輸出匹配的模式
-d 當指定要查找的是目錄而非文件時,必須使用這項參數,不然grep指令將回報信息並中止動做。
-c count統計,統計匹配結果的行數,有n行匹配就輸出數字n

實例:
將/etc/passwd的前10行輸出保存到/tmp/grep.txt,下面grep實例都用這個文本文件。markdown

[root@moli-04 ~]$ head -n 10 /etc/passwd > /tmp/grep.txt
[root@moli-04 ~]$ cat /!$
cat //tmp/grep.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

示例1:查找特定字符串,顯示行號ssh

[root@moli-04 ~]$ grep -n "root" /tmp/grep.txt 
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin

示例2:取反,將不包含root的行輸出,並顯示行號tcp

[root@moli-04 ~]$ grep -nv "root" /tmp/grep.txt 
2:bin:x:1:1:bin:/bin:/sbin/nologin
3:daemon:x:2:2:daemon:/sbin:/sbin/nologin
4:adm:x:3:4:adm:/var/adm:/sbin/nologin
5:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6:sync:x:5:0:sync:/sbin:/bin/sync
7:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8:halt:x:7:0:halt:/sbin:/sbin/halt
9:mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

示例3:-A,-B,-C的使用編輯器

[root@moli-04 ~]$ grep -A 1 root /tmp/grep.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
--
operator:x:11:0:operator:/root:/sbin/nologin

[root@moli-04 ~]$ grep -B 1 root /tmp/grep.txt 
root:x:0:0:root:/root:/bin/bash
--
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

[root@moli-04 ~]$ grep -C 1 root /tmp/grep.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
--
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

第一條命令輸出包含root的行,並輸出它的後一行。
第二條命令輸出包含root的行,並輸出它的前一行。
第三條命令輸出包含rott的行,並輸出它的先後一行。

示例4:-c統計行數,包含root的行有幾行

[root@moli-04 ~]$ grep -c root /tmp/grep.txt 
2

示例5:^,$的使用

# 匹配以r字母爲開頭的行
[root@moli-04 ~]$ grep ^r /tmp/grep.txt 
root:x:0:0:root:/root:/bin/bash
[root@moli-04 ~]#  

# 匹配以nologin單詞爲結尾的行
[root@moli-04 ~]$ grep nologin$ /tmp/grep.txt 
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

示例6:[]的使用

# 查找包含ost或者oot的行
[root@moli-04 ~]$ grep o[os]t /tmp/grep.txt 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

示例7:匹配包含數字和包含小寫字母的行'[0-9]'和'[a-z]'

$ grep '[0-9]' /tmp/grep.txt
$ grep '[a-z]' /tmp/grep.txt

輸出結果太長就不復制進來了,多多動手實踐吧(=゚ω゚)。

示例8:正則表達式實踐
test.txt文件內容以下,注意有空白行。

aaa
bbb
111
222
AAA
BBB

hell world
I love python
pppppython

匹配數字開頭的行:

$ grep '^[0-9]' test.txt
111
222

匹配小寫字母開頭的行:

$ grep '^[a-z]' test.txt
aaa
bbb
hell world
pppppython

匹配空白行,這裏-n顯示行號顯示空白行在第幾行

$ grep -n '^$' test.txt
7:

邏輯匹配或者‘|’,須要使用轉義字符''

$ grep '111\|222' test.txt # 匹配111或者222 
111
222

而且,利用管道

$ grep 'love' test.txt | grep 'python' # 匹配帶有love和python的行
I love python

匹配p字母出現至少4次

$ grep 'p\{4,\}' test.txt # 中括號左右須要使用轉義字符\
pppppython

egrep擴展正則表達式

egrep 在 grep 的基礎上增長了更多的元字符。可是 egrep 不容許使用(),\{\}.下面是egrep支持使用的正則表達式元字符(只列舉新增的)。

字符 說明
+ 匹配一個或多個前面的字符,至少一個
匹配0個或1個起那麼的字符,只能0或者1
豎線 或者(這裏豎線就用中文了,由於markdown表格的豎線轉義不了...)
() 匹配正則集合

sed命令

  • sed 是一種新型的,非交互式的編輯器。它能執行與編輯器 vi 和 ex 相同的編輯任務。
  • sed 編輯器沒有提供交互式使用方式,使用者只能在命令行輸入編輯命令、指定文件名,而後在屏幕上查看輸出。
  • sed 編輯器沒有破壞性,它不會修改文件,除非使用 shell 重定向來保存輸出結果。
  • 默認狀況下,全部的輸出行都被打印到屏幕上。

sed工做流程

sed經過文件或者管道讀取文件內容,但sed默認並不直接修改源文件,而是將讀入的內容複製到緩衝區中,咱們稱之爲模式空間,全部的指令操做都是在模式空間中進行的,而後sed根據對應的指令對模式空間內的內容進行處理並輸出結果,默認輸出至標準輸出(屏幕)。

sed基本語法

用法: sed [選項] {腳本指令} [輸入文件]

sed操做地址匹配
sed 命令在沒有給定的位置時,默認會處理全部行;
sed支持下面幾種地址類型;

示例 說明
number 指定輸入文件的惟一行號
first~step 指定first開始,並指定操做步長爲step。好比1~2,指定第一行、第三行、第五行...爲操做地址。
$ 匹配文件最後一行
/regexp/ 經過正則表達式匹配操做地址,//中間是正則表達式
addr1.addr2 匹配從操做地址1到操做地址2的全部行
addr1,+N 匹配地址1以及後面的N行內容

sed經常使用選項

選項 說明
-n 靜默輸出,sed程序默認在全部腳本指令執行完畢後自動打印模式空間中的內容,該選項能夠屏蔽自動打印
-e 容許多個腳本指令被執行,指令順序會影響結果
-i 修改源文件的內容,慎用
-f 從文件中讀取腳本指令,對編寫自動腳本程序很實用
-r 讓sef支持擴展正則表示式

sed經常使用指令

指令 說明
a 追加(在原先行後追加)
d 刪除
c 更改
i 插入(在原先行前插入)
s 替換
l 打印(顯示非打印字符)
L 打印(不顯示非打印字符)
p 打印
w 保存至文件

部分指令詳解
替換指令:s
使用格式:[address]s/pattern/replacement/flags
address是操做地址,s爲替換指令,pattern須要替換的內容,replacement替換的新內容,flags標記。
flags有幾種:

  • n 表示1-512之間的數字,對模式空間中指定模式的第n次出現進行替換,若有2個hello,替換第二個hello爲world能夠這樣寫s/hello/world/2
  • g 表示全局替換。好比把模式空間中全部的a替換成b,能夠這樣寫s/a/b/g
  • p 打印模式空間的內容.默認狀況下, sed 把輸入行打印在屏幕上,選項-n 用於取消默認打印操縱。選項-n 和命令 p 同時出現時, sed 可打印選定的內容。
  • w file 將模式空間的內容寫到文件file中

sed示例

sed.txt文件內容

$ cat sed.txt 
ONBOOT=yes
IPADDR=192.168.30.6
NETMASK=255.255.255.0
GATEWAY=192.168.30.2
DNS=119.29.29.29

在第一行後面追加TYPE=Ethernet

$ sed '1a TYPE=Ethernet' sed.txt 
ONBOOT=yes
TYPE=Ethernet #追加項
IPADDR=192.168.30.6
NETMASK=255.255.255.0
GATEWAY=192.168.30.2
DNS=119.29.29.29

在第2行前面插入TYPE=Ethernet

$ sed '2i TYPE=Ethernet' sed.txt 
ONBOOT=yes
TYPE=Ethernet # 插入項
IPADDR=192.168.30.6
NETMASK=255.255.255.0
GATEWAY=192.168.30.2
DNS=119.29.29.29

全局替換yes爲no

$ sed 's/yes/no/g' sed.txt 
ONBOOT=no # yes被替換爲no
IPADDR=192.168.30.6
NETMASK=255.255.255.0
GATEWAY=192.168.30.2
DNS=119.29.29.29

刪除第1,2行的內容

$ sed '1,2d' sed.txt 
# 1,2行沒了
NETMASK=255.255.255.0 
GATEWAY=192.168.30.2
DNS=119.29.29.29

匹配以DNS爲開頭的行,並在該行前插入DEVICE=ens33

$ sed '/^DNS/i DEVICE=ens33' sed.txt 
ONBOOT=yes
IPADDR=192.168.30.6
NETMASK=255.255.255.0
GATEWAY=192.168.30.2
DEVICE=ens33 # 插入的行,下一行是以DNS爲開頭
DNS=119.29.29.29

除了直接將操做指令寫在命令行裏,還能夠將操做指令寫在腳本里,而後使用sed -f讀取指令。
建立腳本,內容以下

$ cat sed.sh
# 這個腳本的做用是打印文件的奇數行,須要配合-n選項使用
1~2p

-f讀取指令

$ sed -f sed.sh -n sed.txt 
ONBOOT=yes
NETMASK=255.255.255.0
DNS=119.29.29.29

當須要執行多個指令的時候,能夠有幾種方式。

$ sed -n 's/yes/no/;s/static/dhcp/p' sed.txt #使用分號
$ sed -e 's/yes/no/' -e 's/static/dhcp/' sed.txt # 使用-e選項
$ sed '
>s/yes/no/
>s/static/dhcp/' sed.txt

常見案例1:使用sed命令將文件帶#的行刪除
實際在修改配置文件的時候,配置文件帶有大量的註釋,一般以'#'爲開頭,因而能夠將這些以#爲開頭的行刪掉。

[root@moli-04 tmp]$ cat sed2.txt 
#ajksshdja
jskdjks
#kjklasj
123
$ sed -i '/^#/d' sed2.txt
[root@moli-04 tmp]$ cat sed2.txt 
jskdjks
123

常見案例2:刪除空白行與刪除以數字開頭的行

$ sed '/^$/d' sed.txt
$ sed '/^[0-9]*/d' sed.txt

常見案例3:查找網卡對應ip地址

$ ifconfig | grep -A1 ens33|grep inet|sed s/^.*inet//g | sed 's/netmask.*$//g'
192.168.30.6
相關文章
相關標籤/搜索