SED是一個非交互式文本編輯器,它可對文本文件和標準輸入進行編輯,標準輸入能夠來自鍵盤輸入、文本重定向、字符串、變量,甚至來自於管道的文本,與VIM編輯器相似,它一次處理一行內容,Sed能夠編輯一個或多個文件,簡化對文件的反覆操做、編寫轉換程序等。html
Sed命令的原理:在處理文本時把當前處理的行存儲在臨時緩衝區中,稱爲「模式空間」(pattern space),緊接着用SED命令處理緩衝區中的內容,處理完成後把緩衝區的內容輸出至屏幕或者寫入文件。逐行處理直到文件末尾,然而若是打印在屏幕上,實質文件內容並無改變,除非你使用重定向存儲輸出或者寫入文件。linux
參數格式爲:正則表達式
sed [-Options] [‘Commands’] filename;
sed工具默認處理文本,文本內容輸出屏幕已經修改,可是文件內容其實沒有修改,須要加-i參數即對文件完全修改;shell
-e<script>或--expression=<script> 以選項中指定的script來處理輸入的文本文件。 -f<script文件>或--file=<script文件> 以選項中指定的script文件來處理輸入的文本文件。 -h 或--help 顯示幫助。 -n或--quiet或--silent 僅顯示script處理後的結果。 -r 使用擴展正則表達式 x #x爲指定行號; x,y #指定從x到y的行號範圍; /pattern/ #查詢包含模式的行; /pattern/,/pattern/ #查詢包含兩個模式的行; /pattern/,x #從與pattern的匹配行到x號行之間的行; x,/pattern/ #從x號行到與pattern的匹配行之間的行; x,y! #查詢不包括x和y行號的行; r #從另外一個文件中讀文件; w #將文本寫入到一個文件; y #變換字符; q #第一個模式匹配完成後退出; l #顯示與八進制ASCII碼等價的控制字符; {} #在定位行執行的命令組; p #打印匹配行; = #打印文件行號; a\ #在定位行號以後追加文本信息; i\ #在定位行號以前插入文本信息; d #刪除定位行; c\ #用新文本替換定位文本; s #使用替換模式替換相應模式; & #引用已匹配字符串 first~step #步長,每 step 行,從第 first 開始 $ #匹配最後一行 /regexp/ #正則表達式匹配行 number #只匹配指定行 addr1,addr2 #開始匹配 addr1 行開始,直接 addr2 行結束 addr1,+N #從 addr1 行開始,向後的 N 行 addr1,~N #從 addr1 行開始,到 N 行結束
示例文本:express
[root@localhost ~]# cat test.txt www.test.net www.baidu.com www.taobao.com www.sina.com old old old new new new
替換test.txt文本中old爲new:bash
sed 's/old/new/g' test.txt
打印test.txt文本第一行至第三行:tcp
sed -n '1,3p' test.txt
打印test.txt文本中第一行與最後一行:編輯器
sed -n '1p;$p' test.txt
刪除test.txt第一行至第三行、刪除匹配行至最後一行:工具
sed '1,3d' test.txt sed '/test/,$d' test.txt
刪除test.txt最後6行及刪除最後一行:post
for i in `seq 1 6`;do sed -i '$d' test.txt ;done sed '$d' test.txt
刪除test.txt最後一行:
sed '$d' test.txt
在test.txt查找test所在行,並在其下一行添加word字符,a表示在其下一行添加字符串:
sed '/test/aword' test.txt
在test.txt查找test所在行,並在其上一行添加word字符,i表示在其上一行添加字符串:
sed '/test/i word' test.txt
在test.txt查找以test結尾的行尾添加字符串word,$表示結尾標識,&在Sed中表示添加:
sed 's/test$/& word/g' test.txt
在test.txt查找www的行,在其行首添加字符串word,^表示起始標識,&在Sed中表示添加:
sed '/www/s/^/& word/' test.txt
多個sed命令組合,使用-e參數:
sed -e '/www.jd.com/s/^/&1./' -e 's/www.jd.com$/&./g' test.txt
多個sed命令組合,使用分號「;」分割:
sed -e '/www.jd.com/s/^/&1./;s/www.jd.com$/&./g' test.txt
Sed讀取系統變量,變量替換:
TEST=WWW.test.NET Sed 「s/www.jd.com/$TEST/g」 test.txt
修改Selinux策略enforcing爲disabled,查找/SELINUX/行,而後將其行enforcing值改爲disabled、!s表示不包括SELINUX行:
sed -i '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config sed -i '/SELINUX/!s/enforcing/disabled/g' /etc/selinux/config
去除空格httpd.conf文件空行或者是#號開頭的行
sed '/^#/d;/^$/d' /etc/httpd/conf/httpd.conf
打印是把匹配的打印出來,刪除是把匹配的刪除,刪除只是不用-n 選項
IP 加單引號
echo '10.10.10.1 10.10.10.2 10.10.10.3' |sed -r 's/[^ ]+/"&"/g' "10.10.10.1" "10.10.10.2" "10.10.10.3"
對 1-4 行的 html 進行替換
示例文件:
http://www.baidu.com/index.html http://www.baidu.com/1.html http://post.baidu.com/index.html http://mp3.baidu.com/index.html http://www.baidu.com/3.html http://post.baidu.com/2.html
tail /etc/services | sed '1,4 s/html/txt/' http://www.baidu.com/index.txt http://www.baidu.com/1.txt http://post.baidu.com/index.txt http://mp3.baidu.com/index.txt http://www.baidu.com/3.html http://post.baidu.com/2.html
分組使用,在第2列後面添加 test
tail /etc/services |sed -r 's/(.*) (.*)(#.*)/\1\2test \3/' 3gpp-cbsp 48049/tcp test # 3GPP Cell Broadcast Service isnetserv 48128/tcp test # Image Systems Network Services isnetserv 48128/udp test # Image Systems Network Services blp5 48129/tcp test # Bloomberg locator blp5 48129/udp test # Bloomberg locator com-bardac-dw 48556/tcp test # com-bardac-dw com-bardac-dw 48556/udp test # com-bardac-dw iqobject 48619/tcp test # iqobject iqobject 48619/udp test # iqobject 第一列是第一個小括號匹配,第二列第二個小括號匹配,第三列同樣。將不變的字符串匹配分組,再經過\數字按分組順序反向引用。
基本正則表達式中支持分組,而在擴展正則表達式中,分組的功能更增強大,也能夠說纔是真正的分組
():分組,後面可使用\1 \2 \3...引用前面的括號分組。
處理如下文件內容,將域名取出並進行計數排序,如處理:
http://www.baidu.com/index.html http://www.baidu.com/1.html http://post.baidu.com/index.html http://mp3.baidu.com/index.html http://www.baidu.com/3.html http://post.baidu.com/2.html
獲得以下結果:
域名的出現的次數域名
[root@localhost shell]# cat file | sed -e ' s/http:\/\///' -e ' s/\/.*//' | sort | uniq -c | sort -rn 3 www.baidu.com 2 post.baidu.com 1 mp3.baidu.com [root@codfei4 shell]# awk -F/ '{print $3}' file |sort -r|uniq -c|awk '{print $1"\t",$2}' 3 www.baidu.com 2 post.baidu.com 1 mp3.baidu.com*
將協議與端口號位置調換
tail /etc/services |sed -r 's/(.*)(\<[0-9]+\>)\/(tcp|udp)(.*)/\1\3\/\2\4/' 3gpp-cbsp tcp/48049 # 3GPP Cell Broadcast Service isnetserv tcp/48128 # Image Systems Network Services isnetserv udp/48128 # Image Systems Network Services blp5 tcp/48129 # Bloomberg locator blp5 udp/48129 # Bloomberg locator com-bardac-dw tcp/48556 # com-bardac-dw com-bardac-dw udp/48556 # com-bardac-dw iqobject tcp/48619 # iqobject iqobject udp/48619 # iqobject matahari tcp/49000 # Matahari Broker
字符位置調換
替換 x 字符爲大寫:
# echo "abc cde xyz" |sed -r 's/(.*)x/\1X/' abc cde Xyz
456 與 cde 調換:
# echo "abc:cde;123:456" |sed -r 's/([^:]+)(;.*:)([^:]+$)/\3\2\1/' abc:456;123:cde
註釋匹配行後的多少行
[root@localhost ~]# sed '/5/,+3s/^/@/' 1.txt 1 2 3 4 @5 @6 @7 @8 9 10
註釋指定多行
[root@localhost ~]# sed -r 's/^3|^5|^7/#&/' 1.txt 1 2 #3 4 #5 6 #7 8 9 10
去除開頭和結尾空格或製表符
echo " 1 2 3 " |sed 's/^[ \t]*//;s/[ \t]*$//' 1 2 3
Sed之因此能以行爲單位進行修改文本或者編輯文本,主要緣由是由於它使用了兩個空間:一個是活動的「模式空間」,另外一個是輔助做用的「保留空間」.
模式空間:能夠想象成工程裏面的流水線,全部的數據讀取過來以後就直接在上面進行工做。
保留空間:能夠想象成是倉庫,咱們在進行數據處理的時候,會把數據讀取到保留空間中,做爲數據的暫存區域,須要時再進行調出。
SED高級命令能夠分爲三種功能:
N、D、P:處理多行模式空間的問題; H、h、G、g、x:將模式空間的內容放入保留空間以便接下來的編輯; :、b、t:在腳本中實現分支與條件結構(標籤)。 n #讀取下一個輸入行,用下一個命令處理新的行; N #將當前讀入行的下一行讀取到當前的模式空間。 d #刪除模式空間的全部內容,開始下一個循環 D #刪除模式空間的第一行,開始下一個循環; p #打印當前模式空間的全部內容; P #打印模式空間的第一行,開始下一個循環 h #將模式緩衝區的文本複製到保持緩衝區; H #將模式緩衝區的文本追加到保持緩衝區; x #互換模式緩衝區和保持緩衝區的內容; g #將保持緩衝區的內容複製到模式緩衝區; G #將保持緩衝區的內容追加到模式緩衝區。
在test.txt每行後加入空行,也即每行佔永兩行空間,每一行後邊插入一行空行、兩行空行及前三行每行後插入空行:
sed '/^$/d;G' test.txt #刪除的是匹配的條件行,留下的是模式空間處理的行,G參數是將保持空間內的行追加到模式空間去(保持空間默認是空的)。 sed '/^$/d;G;G' test.txt #後面跟2個G 是將G保持空間內的兩行追加到模式空間 sed '/^$/d;1,3G;' test.txt #1,3G 是隻將追加3行到模式空間
將test.txt偶數行刪除及隔兩行刪除一行:
sed 'n;d' test.txt #n參數將輸入行的下一行顯示出來,然後面的d 正好會將顯示的行進行刪除,測試「sed –n ‘n;p’ file 」 sed 'n;n;d' test.txt, #2個n參數將輸入的的下兩行顯示出來,正好使用d都刪除,造成隔兩行刪一行的效果。
在test.txt匹配行前一行、後一行插入空行以及同時在匹配先後插入空行:
sed '/test/{x;p;x;}' test.txt #x參數是讓模式空間和保持空間互相交換,匹配test時,將模式空間內的數據換成了保持空間內的數據,保持空間默認是空的,因此前一行會變成空行,而後將空行打印出來 sed '/test/G' test.txt #G參數配置上以後將保持空間的內容追加到模式空間去。 sed '/test/{x;p;x;G;}' test.txt #綜合以上兩個參數配置。
在test.txt每行前加入順序數字序號、加上製表符\t及.符號:
sed = test.txt| sed 'N;s/\n/ /' # 「=」等號打印當前行號碼。N參數是配置將當前讀入行的下一行讀取到當前的模式空間,就是把下一行讀到當前的模式空間來,利用s替換換行符,造成數字順序效果。 sed = test.txt| sed 'N;s/\n/\t/' #案例同上 sed = test.txt| sed 'N;s/\n/\./' #案例同上
刪除test.txt行前和行尾的任意空格:
sed 's/^[ \t]*//;s/[ \t]*$//' test.txt #s替換 刪除行前
打印test.txt關鍵詞old與new之間的內容:
sed -n '/old/,/new/'p test.txt #-n參數能夠打印匹配的條件內容行
打印及刪除test.txt最後兩行:
sed '$!N;$!D' test.txt N 讀取下一行並追加輸入到模式空間 D 刪除模式空間的第一行,開始下一個循環 #讀取1,$!條件知足(不是尾行,#N前加$!表示末尾行不執行N),執行N命令,讀取下一行並追加輸入到模式空間,得出1\n2。執行$!D,不是最後一行,因此執行D,刪除模式空間的第一行,開始下一個循環,模式空間由1\n2成了2。讀取第二行,執行 N 命令,此時模式空間是 3\n4,執行 D 命令刪除模式空間第一行 3,剩餘4,直到執行N讀入第5行,$!條件不知足(不是尾行),不執行N命令:繼續讀入6行,這裏模式空間爲:5\n6,$!D,由於是最後一行,因此不執行D,控制流到達腳本底部,輸出模式空間的內容
sed 'N;$!P;$!D;$d' test.txt P 打印模式空間的第一行 N 讀取下一行並追加輸入到模式空間 D 刪除模式空間的第一行,開始下一個循環 d 刪除匹配的行 #讀取第一行,執行N,此時得出1\n2,P打印從開始到第一個\n的內容,執行$!D,不是最後一行,因此執行D,刪除模式空間的第一行,開始下一個循環,模式空間由1\n2成了2,$d 是由於不是末行因此不執行,讀取第二行,執行 N 命令,此時模式空間是 3\n4,執行 P 命令顯示模式空間第一行 3,執行D,刪除模式空間的第一行,剩餘4,讀取第5行,執行N,將第6行進行讀取,執行$!P,由於是最後一行不執行P,執行$!D,由於是最後一行,不執行D,最後執行$d,刪除模式空間5/6行。
合併上下兩行,也即兩行合併:
sed '$!N;s/\n/ /' test.txt #N前加$!表示末尾行不執行N sed 'N;s/\n/ /' test.txt
標籤能夠控制流,實現分支判斷。
: lable name 定義標籤 b lable 跳轉到指定標籤,若是沒有標籤則到腳本末尾 t lable 跳轉到指定標籤,前提是 s///命令執行成功
將換行符替換成逗號
方法 1:
seq 6 |sed 'N;s/\n/,/' 1,2 3,4 5,6
這種方式並不能知足咱們的需求,每次 sed 讀取到模式空間再打印是新行,替換\n 也只能對 N 命令,追加後的 1\n2 這樣替換。
這時就能夠用到標籤了:
seq 6 |sed ':a;N;s/\n/,/;b a' 1,2,3,4,5,6 看看這裏的標籤使用,:a 是定義的標籤名,b a 是跳轉到 a 位置。 sed 讀取第一行 1,N 命令讀取下一行 2,此時模式空間是 1\n2$,執行替換,此時模式空間是1,2$,執行 b 命令再跳轉到標籤 a 位置繼續執行 N 命令,讀取下一行 3 追加到模式空間,此時模式空間是 1,2\n3$,再替換,以此類推,不斷追加替換,直到最後一行 N 讀不到下一行內容退出。
方法 2:
seq 6 |sed ':a;N;$!b a;s/\n/,/g' 1,2,3,4,5,6 先將每行讀入到模式空間,最後再執行全局替換。$!是若是是最後一行,則不執行 b a 跳轉,最後執行全局替換。 seq 6 |sed ':a;N;b a;s/\n/,/g' 1 2 3 4 5 6 能夠看到,不加$!是沒有替換,由於循環到 N 命令沒有讀到行就退出了,後面的替換也就沒執行。
每三個數字加個一個逗號
# echo "123456789" |sed -r 's/([0-9]+)([0-9]+{3})/\1,\2/' 123456,789 # echo "123456789" |sed -r ':a;s/([0-9]+)([0-9]+{3})/\1,\2/;t a' 123,456,789 # echo "123456789" |sed -r ':a;s/([0-9]+)([0-9]+{2})/\1,\2/;t a' 1,23,45,67,89 執行第一次時,替換最後一個,跳轉後,再對 123456 匹配替換,直到匹配替換不成功,不執行 t 命令。
忽略大小寫匹配(I )
# echo -e "a\nA\nb\nc" |sed 's/a/1/Ig' 1 1 b c
獲取總行數(# )
seq 10 |sed -n '$='
Sed 腳本使用編寫方法
<1>從文件讀入命令
sed -f sed.sh sed.sh文件內容: s/root/yerik/p s/bash/csh/p
<2>直接運行腳本 ./sed.sh /etc/passwd
#!/bib/sed -f s/root/yerik/p s/bash/csh/p
1,刪除文件每行的第一個字符。
sed -n 's/^.//gp' /etc/passwd sed -nr 's/(.)(.*)/\2/p' /etc/passwd sed -r 's/^.//g' test.txt
2,刪除文件每行的第二個字符。
sed -nr 's/(.)(.)(.*)/\1\3/p' /etc/passwd sed -r 's/(^.)(.)/\1/g' test.txt
3,刪除文件每行的最後一個字符。
sed -nr 's/.$//p' /etc/passwd sed -nr 's/(.*)(.)/\1/p' /etc/passwd sed -r 's/(.)$//g' test.txt
4,刪除文件每行的倒數第二個字符。
sed -nr 's/(.*)(.)(.)/\1\3/p' /etc/passwd sed -r 's/(.)(.)$/\2/g' test.txt
5,刪除文件每行的第二個單詞。
sed -nr 's/([^a-Z]*)([a-Z]+)([^a-Z]+)([a-Z]+)(.*)/\1\2\3\5/p' /etc/passwd sed -r 's/([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)(.*)/\1\2\4\5/' test.txt
6,刪除文件每行的倒數第二個單詞。
sed -nr 's/(.*)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]*)/\1\2\4\5\6/p' /etc/passwd sed -r 's/([a-Z]+)([^a-Z])([a-Z]+)$/\2\3/g' test.txt
7,刪除文件每行的最後一個單詞。
sed -nr 's/(.*)([^a-Z]+)([a-Z]+)([^a-Z]*)/\1\2\4/p' /etc/passwd sed -r 's/([a-Z]+)$//g' test.txt sed -r 's/(.*)([^a-Z]+)([a-Z]+)/\1\2/' test.txt
8,交換每行的第一個字符和第二個字符。
sed -nr 's/(.)(.)(.*)/\2\1\3/p' /etc/passwd sed -r 's/(.)(.)/\2\1/' test.txt
9,交換每行的第一個字符和第二個單詞
sed -r 's/(^.)([^a-Z]*)([a-Z]+)([^a-Z]+)([a-Z]+)/\5\2\3\4\1/' test.txt
9,交換每行的第一個單詞和第二個單詞。
sed -nr 's/([^a-Z]*)([a-Z]+)([^a-Z]+)([a-Z]+)(.*)/\1\4\3\2\5/p' /etc/passwd
10,交換每行的第一個單詞和最後一個單詞。
sed -r 's/([a-Z]+)([^a-Z]+)(.*)([^a-Z]+)([a-Z]+)/\5\2\3\4\1/' test.txt
11,刪除一個文件中全部的數字。
sed 's/[0-9]*//g' test.txt
12,刪除每行開頭的全部空格。
sed -n 's/^\ *//p' /etc/passwd sed -nr 's/( *)(.*)/\2/p' test.txt sed 's/^ *//' test.txt
13,用製表符替換文件中出現的全部空格。
sed -n 's/\ /\t/gp' test.txt sed -r 's/( +)/\t/g' test.txt sed 's/ /\t/g' test.txt
14,把全部大寫字母用括號()括起來。
sed -nr 's/([A-Z])/(&)/gp' test.txt sed -n 's/[A-Z]/(&)/gp' test.txt
15,打印每行3次。
sed 'p;p' test.txt sed -n 'p;p;p' test.txt
16,隔行刪除。
sed -n '1~2p' test.txt sed '1d;n;d' ww.txt sed '1~2d' ww.txt sed '0~2d' ww.txt
17,把文件從第22行到第33行復制到第44行後面。
sed '1,21h;22h;23,33H;44G' pass cat -n /etc/passwd | sed '22h;23,33H;44G'
18,把文件從第22行到第33行移動到第44行後面。
sed '22{h;d};23,33{H;d};44G' pass cat -n /etc/passwd | sed '22{h;d};23,33{H;d};44G'
19,只顯示每行的第一個單詞。
sed -nr 's/([^a-Z]*)([a-Z]+)([^a-Z]+)(.*)/\2/p' /etc/passwd sed -r 's/([a-Z]+)(.*)/\1/' test.txt
20,打印每行的第一個單詞和第三個單詞。
sed -nr 's/([^a-Z]*)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)(.*)/\2--\4/p' /etc/passwd sed -r 's/([^a-Z]*)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)(.*)/\2\6/' test.txt
21,將格式爲 mm/yy/dd 的日期格式換成 mm;yy;dd
date +%m/%Y/%d |sed -n 's#/#;#gp'
22, 逆向輸出
cat a.txt ABC DEF XYZ sed '1!G;h;$!d' a.txt 輸出樣式變成 XYZ DEF ABC
1. /bin/cp /etc/passwd /root/test.txt ; sed -n '1,$'p test.txt 2. sed -n '3,10'p test.txt 3. sed -n '/root/'p test.txt 4. sed '15,$'d test.txt 5. sed '/bash/'d test.txt 6. sed 's/root/toor/g' test.txt 7. sed 's#sbin/nologin#bin/login#g' test.txt 8. sed '5,10s/[0-9]//g' test.txt 9. sed 's/[^0-9a-zA-Z]//g' test.txt 10. sed 's/\(^[a-Z]*\)\([^a-Z].*\)\([^a-Z]\)\([a-Z]*$\)/\4\2\3\1/' test.txt 11. sed 's#\([^0-9][^0-9]*\)\([0-9][0-9]*\)\([^0-9].*\)\([^a-zA-Z]\)\([a-zA-Z][a-zA-Z]*$\)#\1\5\3\4\2#' test.txt 12. sed 's#\([^0-9][^0-9]*\)\([0-9][0-9]*\)\([^0-9].*$\)#\1\3\2#' test.txt 13. sed '20,$s/^.*$/aaa:&/' test.txt