1. 程式人生 > >一天一命令-sed

一天一命令-sed

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