一天一命令-sed
一天一命令-sed
sed - stream editor for filtering and transforming text
sed 4.2.2
sed是一種流編輯器,讀取一行,處理一行,輸出一行。sed先讀取文件中的一行內容存儲到被稱為模式空間(pattern space)的臨時緩沖區中,接著根據設定的條件來處理緩沖區中的內容,多個條件則多次處理,處理完成後,輸出到屏幕,接著讀取和處理下一行。源文件內容並沒有改變,除非使用重定向存儲輸出。Sed主要用來自動編輯一個或多個文件;簡化對多個文件執行相同的編輯處理工作;編寫轉換程序。
【重要】sed處理的是緩沖區的行數據,不影響源數據,一次讀取,可以多次處理,後續的編輯命令都是應用前面命令編輯後輸出的結果,所以一定要註意編輯命令的順序問題。sed的處理順序,先讀取文件中的一行數據保存到緩沖區,再查看地址位置是否匹配,匹配則執行命令,是先匹配起始地址,匹配則執行編輯命令,不匹配則繼續查看下一個地址位置或繼續讀取下一行。
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... OPTION: -n 僅顯示經過sed處理後的行數據,通常配合-p使用,即打印匹配行,相當於grep -e 多次編輯,支持多個條件匹配和處理,順序執行,註意多次處理指的是處理緩沖區中讀取的行數據,而不是源文件的行數據,即一次讀取,多次處理。 -f 從指定的文件中讀取編輯腳本 -i+後綴名 指定後綴名並先備份源文件,再編輯源文件;不加後綴名表示直接編輯源文件 -r 使用擴展的正則表達式
-e的理解如下,其實等同於cmd1;cmd2;...
#more f1
a
b
c
d
#sed -n -e ‘1,3p‘ -e ‘2anewline‘ -e ‘2d‘ f1 //先讀取第一行到緩沖區,並依次匹配三個條件進行處理,處理一次輸出一次
a //讀取第一行,匹配第一個條件,執行打印輸出,不匹配後兩個條件,則第一行處理結束
b //讀取第二行,匹配第一個條件,執行打印輸出
newline //繼續匹配第二個條件,即在匹配行的下一行添加newline行,繼續匹配第三個條件,刪除第二行數據,註意這裏刪除的是緩沖區中的數據
c //讀取第三行,匹配第一個條件,打印輸出,不匹配後兩個條件,則第三行處理結束
#sed -n -e ‘2d‘ -e ‘1,3p‘ -e ‘2abc‘ f1
a //讀取第一行內容,不匹配第一個條件,不處理,匹配第二個條件,打印輸出,不匹配第三個條件,不處理,第一行處理結束
c //讀取第二行內容,匹配第一個條件,刪除處理,匹配後續兩個條件,但緩沖區內容已被刪除,所以輸出為空,即最後不顯示第二行。讀取第三行,匹配第二個條件,打印輸出。
地址定界:
(1)不給地址:對全文進行處理
(2)單地址:
#: 指定行
/pattern/ :被指定模式匹配到的每一行
(3)地址範圍:
#,#
#,+#
#,/pat1/
/pat1/,/pat2/
(4) ~ :步進
1~2 奇數行
2~2 偶數行
元字符集
^ 錨定行的開始,如/^sed/匹配所有以sed開頭的行。
$ 錨定行的結束,如/sed$/匹配所有以sed結尾的行。
. 匹配一個非換行符的字符,如/s.d/匹配s後接一個任意字符,然後是d。
* 匹配零個或多個字符,如/*sed/匹配任何一個或多個字符後跟sed的行。
[] 匹配一個指定範圍內的字符,如/[Ss]ed/匹配sed和Sed。
[^] 匹配一個不在指定範圍內的字符,如/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一個字母開頭,緊跟ed的行。
\(..\) 保存匹配的字符,如s/\(love\)able/\1rs,loveable被替換成lovers。
& 保存搜索字符用來替換其他字符,如s/love/**&**/,love這成**love**。
\< 錨定單詞的開始,如/\<love/匹配包含以love開頭的單詞的行。
\> 錨定單詞的結束,如/love\>/匹配包含以love結尾的單詞的行。
x\{m\} 重復字符x,m次,如/o\{5\}/匹配包含5個o的行。
x\{m,\} 重復字符x,至少m次,如/o\{5,\}/匹配至少有5個o的行。
x\{m,n\} 重復字符x,至少m次,不多於n次,如/o\{5,10\}/匹配5--10個o的行。
Sed 命令地址匹配問題總結——轉載於http://kodango.com
0,addr2和1,addr2這兩種寫法一般情況下是相同的,但是有不同的情況
seq 6 | sed -n ‘0,/1/p‘ //打印第一行,/1/是正則,因為第一行的內容就是1,0表示默認匹配第一行
seq 6 | sed -n ‘1,/1/p‘ //打印所有內容,why?
為什麽不相同呢? 解釋如下:
0, addr2 這種形式默認第一個地址是匹配的,然後直到add2匹配為止。因此上述情況,只要看每一行是否匹配第二個地址addr2就可以了,因為第一行是匹配的,所以打印到第一行為止。
1, addr2 這種形式就是普通形式,不管addr2匹配與否,第一行是匹配的,然後讀入第二行,發現不匹配addr2,繼續讀,直到最後也沒找到匹配,因此打印從第1行到最後一行之間的所有內容。
地址範圍addr1, addr2的匹配方式,從匹配addr1的那行開始,打開匹配開關,直到匹配addr2的那行結束,關閉匹配開關,之後的行會忽略這個地址範圍,不再做匹配。
如果addr1是行號,新讀入行的行號大於addr1,則匹配;小於addr1,則不匹配。
如果addr2是行號,新讀入行的行號小於addr2,則匹配,繼續往下讀;大於addr2,則不匹配,關閉匹配開關。
$ seq 6 | sed ‘1,2d‘ | sed ‘1,2d‘ //結果返回5 6
$ seq 6 | sed -e ‘1,2d‘ -e ‘1,2d‘ //結果返回4 5 6
顯然這兩種情況使用sed的命令形式是不一樣的,第一種利用管道使用了sed兩次,結果返回5 6,沒什麽問題;第二種情況在同一個sed命令中使用了兩次1,2d,按常理應該是返回 3 4 5 6,結果返回 4 5 6,第3行竟然也被意外地刪除了,為什麽呢?第二條命令解釋:
1.首先第一行被讀入,遇到第一組expression -> 1,2d,第一行匹配成功(打開匹配開關),執行d命令,d命令清空模式空間的內容,因此不會再執行接下來的命令。
2.繼續從標準輸入讀入第二行,同1
3.讀入第三行,第一組expression匹配失敗(因為3>2),因此試著執行第二組expersson->1,2d,因為3>1,打開匹配開關,執行d。(這裏是關鍵)
4.讀入第四行,執行第二組expersson->1,2d,因為4>2,匹配失敗,關閉匹配開關,同時也不執行d。
5.因此,最後第1 2 3行被刪除。
編輯命令
a\ 在當前行下面插入一行文本,支持使用 \n 實現多行追加。
i\ 在當前行上面插入一行文本。
c\ 把選定的行改為新的文本。
d 刪除模式空間匹配的行。
D 刪除模式空間的第一行。刪除當前模式空間開端至 \n 的內容(不再傳至標準輸出),放棄之後的命令,但是對剩余模式空間重新執行sed
s 替換指定字符 s/a/string,只有a的位置才支持正則表達式,後邊替換的只能是字符串。
h 把模式空間中的內容覆蓋到內存中的緩沖區。
H 把模式空間中的內容追加到內存中的緩沖區。
g 讀取內存緩沖區的內容覆蓋到模式空間中的內容。
G 讀取內存緩沖區的內容追加到模式空間中的內容。
l 列表顯示不能打印的字符清單。
n 讀取匹配到的行的下一行覆蓋至模式空間。
N 讀取匹配到的行的下一行追加至模式空間。
p 顯示模式空間中的內容。
P (大寫) 打印模式空間的第一行。
q 退出Sed。
b lable 分支到腳本中帶有標記的地方,如果分支不存在則分支到腳本的末尾。
r file 從file中讀行。
t label if分支,從最後一行開始,條件一旦滿足或者T,t命令,將導致分支到帶有標號的命令處,或者到腳本的末尾。
T label 錯誤分支,從最後一行開始,一旦發生錯誤或者T,t命令,將導致分支到帶有標號的命令處,或者到腳本的末尾。
w file 保存模式匹配的行至指定文件。
W file 讀取指定文件的文本至模式空間中匹配到的行後。
! 模式空間中匹配行取反處理。
= 打印當前行號。
# 把註釋擴展到下一個換行符以前。
替換
s/// 查找替換,支持使用其它分隔符,s@@@,s###
替換標記:
g 行內全局替換
p 顯示替換成功的行
w /PATH/TO/SOMEFILE 將替換成功的行保存至文件中
\1 組匹配標記
& 匹配字符串標記
案例:
sed ‘‘ f1 //顯示文件內容,相當於cat sed -n ‘‘ f1 sed ‘2p‘ /etc/passwd sed -n ‘2p‘ /etc/passwd //只顯示匹配到的行 sed -n ‘1,3p‘ /etc/passwd sed -n ‘/root/p‘ /etc/passwd sed -n ‘2,/root/p‘ /etc/passwd sed ‘/root/a\superman‘ /etc/passwd //在匹配到root的行的下一行插入superman sed ‘/root/i\superman‘ /etc/passwd //上一行 sed ‘/root/c\superman‘ /etc/passwd //替換匹配到的行 sed ‘1,3wa‘ f1 //匹配f1文件的1-3行並保存到a文件中 sed -n ‘/^$/=‘ f1 //顯示空行行號,但是不會顯示tab空行的行號 sed ‘/^$/d‘ f1 //刪除空行,但是不會刪除tab空行 sed ‘1,5d‘ f1 sed ‘2,$d‘ f1 //刪除從第二行到末尾的所有行 sed ‘$d‘ f1 //刪除空白行 sed ‘/^root/d‘ passwd //刪除以root開頭的行 nl passwd | sed ‘2,10d‘ nl passwd | sed -n ‘/root/p‘ sed ‘s/root/admin/g‘ passwd sed -n ‘s/a/d/p‘ f1 //僅顯示替換的行 sed -n ‘s/root/&superman/p‘ passwd sed -n ‘s/root/superman&/p‘ passwd echo aaaaaa | sed ‘s/a/A/g‘ //全局替換 echo aaaaaa | sed ‘s/a/A/2‘ //表示只替換第二個匹配項,顯示為aAaaaa echo aaaaaa | sed ‘s/a/A/2g‘ //從第二個匹配到的開始替換 echo aaaaaa | sed ‘s/a/A/3g‘ //第三個,顯示結果為aaAAAA,第n個,就是ng echo this is a test line | sed ‘s/\w\+/[&]/g‘ //正則表達式\w\+表示匹配每一個單詞,&表示匹配到單詞,顯示結果為[this] [is] [a] [test] [line] sed -i.bak ‘2d‘ f1 //編輯前先備份文件f1為f1.bak,然後編輯f1文件 sed -n ‘p;n‘ f1 //顯示奇數行 sed -n ‘n;p‘ f1 //顯示偶數行 sed -n ‘1~2p‘ f1 //奇數行 sed -n ‘2~2p‘ f1 //偶數行 sed ‘n;d‘ f1 //顯示奇數行 sed ‘1!G;h;$!d‘ f1 //倒序顯示 sed -n ‘1!G;h;$p‘ f1 //倒序 sed ‘N;D‘ f1 //顯示最後一行 sed ‘$!N;$!D‘ f1 //顯示最後兩行 sed ‘$!d‘ f1 //刪除除了最後一行的行,即保留最後一行 sed ‘G‘ f1 //為每一行增加一個空行 sed ‘g‘ f1 //清空文件 seq 10 | sed -n ‘N;pa----‘ //按照每兩行數據為分隔並顯示,即將多行分隔為兩行兩行顯示 seq 10 | sed -n ‘N;P‘ //只打印最後一行 sed ‘/^S/d;G‘ f1 sed ‘3q‘ f1 name=root;sed -n "/$name/p" passwd //匹配變量需要使用雙引號"" nl passwd | sed -n ‘/root/{s/bash/shell/;p}‘ //表示找到root行,執行後面花括號的一組命令,每個命令之間用分號隔開 sed ‘s/^/# /‘ f1 //在每行的開頭添加#號 sed -i [email protected]\.[email protected]@‘ test //匹配IPADDR的行,把10.1替換成10.12,符號.需要轉義 sed -n ‘$=‘ f1 //統計行數,相當於wc -l sed ‘s/^[ \t]*//‘ 刪除每一行開頭的空白(空格,TAB)左對齊排列全文 sed ‘s/[ \t]*$//‘ 刪除每一行最後的空白(空格,TAB) sed ‘/a/{s//&b/;s/^/+ /}‘ f1 //在a後面增加b,同時在被修改的行前面增加+號 sed -e ‘1,3p‘ -e ‘2d‘ f1 //-e可以省略,此命令可以簡寫為sed ‘1,3p;2d‘ f1 刪除空白行和#開頭的行 sed -e ‘/^#/d‘ -e ‘/^[[:space:]]*$/d‘ /etc/fstab 取基名和目錄名 echo "/etc/sysconfig/network-scripts" |sed -r ‘s@(^/.*/)([^/]+/?)@\[email protected] echo "/etc/sysconfig/network-scripts" |sed -r ‘s@(^/.*/)([^/]+/?)@\[email protected] 取ifconfig eth0中本機IP ifconfig eth0|sed -n -e ‘2s/^.*r://‘ -e ‘2s/ .*//p‘ /sbin/ifconfig eth0 | grep ‘inet addr‘ | sed ‘s/^.*addr://g‘ | sed ‘s/Bcast.*$//g‘
本文出自 “rackie” 博客,請務必保留此出處http://rackie386.blog.51cto.com/11279229/1941606
一天一命令-sed