sed命令使用技巧

sed全稱 Stream EDitor, 行編輯器 ,是一種流編輯器,它一次處理一行內容。處理時,把當前處理的行存儲在臨時緩衝區中,稱爲“模式空間”(pattern space),接着用sed命令處理緩衝區中的 內容,處理完成後,把緩衝區的內容送往屏幕。然後讀入下行,執行下一個循環。 如果沒有使諸如‘D’的特殊命令,那會在兩個循環之間清空模式空間,但不會清 空保留空間。這樣不斷重複,直到文件末尾。文件內容並沒有改變,除非你使用重 定向存儲輸出。
sed主要用來自動編輯一個或多個文件,簡化對文件的反覆操作,編寫轉換程序等

使用格式:sed [OPTION]... {script} [input-file]...

選項說明:
-n 不輸出模式空間的內容到屏幕
-r 支持使用擴展正則表達式
-e 多點編輯,即能夠多次對模式空間內容進行編輯
-f /Path/script_file 從指定路徑讀取編輯腳本
-i.bak 單純-i是直接修改文件,加上.bak或者任意.xxx 表示先備份源文件再修改

script說明:
用來做地址界定用,以下幾種地址界定形式:
1 不寫地址界定表示全文檢索;
2 #,# 其中#代表行號,表示從第幾行到第幾行;#,+#表示從某一行往後檢索+#行;
3 /part/ 能夠被正則表達part匹配的所有行;也可以和行號配合使用#,/part/表示從某一行開始匹直到匹配到part模式。注意沒有/part/,#這種界定格式
4 $表示最後一行,和上面的界定符配合使用#,$ 表示第#行到最後一行;
5 ~表示步進,例如1~2奇數行,2~2偶數行,3~5從第三行開始每5行取行

編輯命令:
在地址界定完成後就需要指定對界定到的行如何處理,具體處理指令如下
d: 刪除模式空間匹配的行,並立即啓用下一輪循環
p:打印當前模式空間內容,追加到默認輸出之後
a []text:在指定行後面追加文本 支持使用\n實現多行追加
i []text:在行前面插入文本
c []text:替換行爲單行或多行文本
w /path/somefile: 保存模式匹配的行至指定文件
r /path/somefile:讀取指定文件的文本至模式空間中 匹配到的行後
=: 在界定到的每一行的前面插入該行行號
!:模式空間中匹配行取反處理
n 讀取下一個輸入行,用下一個命令處理新的行而不是用第一個命令

以上選項即命令可以組成如下格式,
sed -選項 '地址界定編輯命令 ' 被編輯文本
地址界定符完成後緊跟編輯命令
例如:
sed -n '10,$aHello Sed' /etc/passwd
表示取/etc/passwd 第10行到最後一行通過編輯命令a在取到的每一行後面添加一行內容Hello Sed,但匹配的到行即模式空間內容不輸出到屏幕,因此只會輸出10到最後一行每一行後面添加的Hello Sed行,以下是結果:

[root@centos7 16:14:30 ~]#sed  -n '45,$aHell Sed' /etc/passwd
Hell Sed
Hell Sed
Hell Sed
Hell Sed
Hell Sed

如果不使用-n選項則會是以下效果:

[root@centos7 16:15:57 ~]#sed   '45,$aHell Sed' /etc/passwd | tail -12
mongodb:x:1003:1005::/home/mongodb:/bin/bash
base:x:1004:1006::/home/base:/bin/bash
bash:x:1005:1007::/home/bash:/bin/bash
Hell Sed
testbash:x:1006:1008::/home/testbash:/bin/bash
Hell Sed
nologin:x:1008:1010::/home/nologin:/sbin/nologin
Hell Sed
sh:x:1009:1011::/home/sh:/bin/bash
Hell Sed
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
Hell Sed
[root@centos7 16:16:02 ~]#

假設這裏滿足了對文件修改的需求,就可以將參數選項緩存-i讓修改內容在文件中立即生效

再例如,需要刪除某些行,則可以這麼處理:

[root@centos7 16:25:00 ~]#sed  '1,+40d'  /etc/passwd
docker:x:1002:1004::/home/docker:/bin/bash
mongodb:x:1003:1005::/home/mongodb:/bin/bash
base:x:1004:1006::/home/base:/bin/bash
bash:x:1005:1007::/home/bash:/bin/bash
testbash:x:1006:1008::/home/testbash:/bin/bash
nologin:x:1008:1010::/home/nologin:/sbin/nologin
sh:x:1009:1011::/home/sh:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
[root@centos7 16:25:19 ~]#
表示刪除從1第行到第41行如果這裏加上-i 選項則對/etc/passwd生效

以上是地址界定配合編輯命令的使用,下面介紹查找替換命令s///的使用:
s/// 或者將/符號換成其它分隔符都可以例如,s@@@ s###
在查找替換命令s///後可以跟一些替換標記來,例如
s///g 表示行內全局替換,即每一行所有符合模式的字符都會被替換
s///p 查找替換後並打印
w /PATH/TO/SOMEFILE:將替換成功的行保存至文件中

下面列舉以下典型的例子幫助個人理解(centos6系統):

1、複製/etc/rc.d/rc.sysinit文件至/tmp目錄,將/tmp/rc.sysinit文件中的以至少一個空白字符開頭的行的行首加#。

[root@centos6 15:08:14 ~]#cp /etc/rc.d/rc.sysinit /tmp
[root@centos6 15:16:08 ~]#sed -n '13,13p' /etc/rc.sysinit 
    . /etc/sysconfig/network
[root@centos6 15:16:25 ~]#sed  's/\(^[[:space:]]\)/#\1/g' /tmp/rc.sysinit | sed -n '13,13p'
#    . /etc/sysconfig/network
[root@centos6 15:17:05 ~]#
這裏只是爲了方便展示出結果因此只打印出更改後生效的第13行

2 將/etc/yum.repos.d/repobak/CentOS-Media.repo文件中所有的enabled=0或gpgcheck=0的最後的0修改爲1

[root@centos6 15:23:31 ~]#cat !$
cat /etc/yum.repos.d/repobak/CentOS-Media.repo
# CentOS-Media.repo
#
#  This repo can be used with mounted DVD media, verify the mount point for
#  CentOS-6.  You can use this repo and yum to install items directly off the
#  DVD ISO that we release.
#
# To use this repo, put in your DVD and use it with the other repos too:
#  yum --enablerepo=c6-media [command]
#  
# or for ONLY the media repo, do this:
#
#  yum --disablerepo=\* --enablerepo=c6-media [command]

[c6-media]
name=CentOS-$releasever - Media
baseurl=file:///media/CentOS/
        file:///media/cdrom/
        file:///media/cdrecorder/
gpgcheck=0
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
[root@centos6 15:23:41 ~]#
可以看到兩個參數的值都是0,使用sed修改:
[root@centos6 15:23:41 ~]#sed   -e 's/enabled=0/enabled=1/' -e 's/gpgcheck=0/gpgcheck=1/'  /etc/yum.repos.d/repobak/CentOS-Media.repo | tail -3
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
也可以寫成:
[root@centos6 15:25:17 ~]#sed 's/enabled=0/enabled=1/;s/gpgcheck=0/gpgcheck=1/'  /etc/yum.repos.d/repobak/CentOS-Media.repo | tail -3
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

3 打印奇數行和偶數行
偶數行:

[root@centos6 15:33:17 ~]#sed -n 'n;p' /etc/passwd
[root@centos6 15:35:00 ~]#sed -n '2~2p' /etc/passwd
奇數行:
[root@centos6 15:35:55 ~]#sed -n '1~2p' /etc/passwd
[root@centos6 15:36:00 ~]#sed -n 'p;n' /etc/passwd

4 n命令的作用

[root@centos7 17:18:18 ~]#cat passwd.out 
docker:x:1002:1004::/home/docker:/bin/bash
mongodb:x:1003:1005::/home/mongodb:/bin/bash
base:x:1004:1006::/home/base:/bin/bash
bash:x:1005:1007::/home/bash:/bin/bash
testbash:x:1006:1008::/home/testbash:/bin/bash
nologin:x:1008:1010::/home/nologin:/sbin/nologin
sh:x:1009:1011::/home/sh:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
[root@centos7 17:18:27 ~]#sed  '/docker/n;s/mongodb/manguo/g;' passwd.out 
docker:x:1002:1004::/home/docker:/bin/bash
manguo:x:1003:1005::/home/manguo:/bin/bash
base:x:1004:1006::/home/base:/bin/bash
bash:x:1005:1007::/home/bash:/bin/bash
testbash:x:1006:1008::/home/testbash:/bin/bash
nologin:x:1008:1010::/home/nologin:/sbin/nologin
sh:x:1009:1011::/home/sh:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
[root@centos7 17:18:29 ~]#
這裏先使用匹配模式匹配到docker行,即第一行,n命令表示繼續讀取docker行的後一行並將讀取到的行交給s查找替換來處理,查找替換將mongodb替換成manguo

另外需要注意的sed匹配的貪婪模式,如下圖
sed命令使用技巧
圖中第一個命令還不太能說明問題,在第二個匹配結果有兩組,sed先匹配到root開頭的第一行保存後,再去匹配bin,此時從第二行讀入發現恰好也匹配到了bin,因此本次/root/,/bin/模式匹配完成。但是sed不會停止反而會繼續往下匹配。因此接下來發現第三行(operator開頭行)中包含root 然後保存,再繼續往下一行去匹配bin,找到後保存。
這時候就有了第二組/root/,/bin/模式。sed會繼續再往下搜索但是沒有再匹配到/root/,/bin/模式而結束。打印輸出匹配到的兩組結果!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章