##sed簡介 sed命令說簡單也簡單,說複雜也複雜,看你怎麼用。若是隻是簡單的使用的話知道s,a,i,d命令就能夠了。若是要深刻一點的瞭解的話就要理清楚sed的處理流程,知道什麼是pattern space,知道什麼是hold space,它們的做用是什麼。 對於sed命令剛剛開始感受很亂,傻傻分不清楚位置匹配命令。這裏有一個小的技巧,發現對於sed命令有一個比較明顯的特色,就是大多數的模式都是先匹配位置在執行命令。這個須要在使用過程當中多注意,慢慢的就會發現基本上均可以替換爲這中模式。正則表達式
###pattern space(模式空間) 與 hold space(持有空間) pattern space能夠看作是sed讀取行存放和處理的內存空間,sed是按行來處理數據的,sed每從輸入流中讀取一行就存放在pattern space中,而後進行處理,處理後的結果也存放中pattern space中,而後在讀取下一行進行處理,在讀取下一行以前會先清楚pattern space,有時候咱們須要pattern space處理結果後面用怎麼辦呢,由於pattern space每一次讀取新行以前都會清空,因此不能緩存結果,爲了解決這個問題,sed就另外申請了一個空間,這個空間就是hold space,咱們能夠把pattern space中的處理結果存放在hold space中。shell
###sed處理流程 數據庫
###sed命令與匹配概覽 編程
##sed基本命令 sed命令主要用來處理文件,若是把文件當作數據庫的話,sed命令完成的操做基本上也就是增刪改查,查詢比較少,查詢主要是爲了修改。若是隻是查詢的話能夠考慮grep。緩存
###刪除app
#刪除 sed '2d' fileName #刪除fileName文件的第二行。 sed '2,$d' fileName #刪除fileName文件的第二行到末尾全部行。 sed '$d' fileName #刪除fileName文件的最後一行。 sed '/^love/d' fileName #刪除fileName文件全部以love開始的行。
對於刪除須要注意的是刪除的匹配到的整行,而不是刪除的匹配,例如sed '/love/d' fileName 就是刪除fileName中包含love的全部行,而不是隻是刪除love。編程語言
###替換ide
#替換 sed '1,10y/abc/ABC/' fileName #將1到10行中的abc替換爲ABC sed '1,10s/abc/ABC/' fileName #將1到10行中的abc替換爲ABC #對於s命令更加常見的是沒有位置的 #將fileName中每一行的第一個pattern(可使用正則)替換爲expect sed 's/pattern/expect/' fileName #若是要所有替換可使用g(sed中有2個g一個是表示全局,一個表示從 #hold space 去數據到pattern space,這裏和多數其它正則表達式同樣表示全局) sed 's/pattern/expect/g' fileName #對於替換除了y,s還有一個c命令,通常用法是c\ sed '1 c\sed c change' fileName #把fileName中的第一行有sed c change替換 #對於替換命令y 和 s的區別在於y是以單個字符爲單位進行替換,s是以總體進行替換 echo "abc------a-b-c" | sed 'y/abc/xyz/' #結果:xyz------x-y-z echo "abc------a-b-c" | sed 's/abc/xyz/' #結果:xyz------a-b-c
###添加測試
#給sedswap.sh文件的第一行加上#!/bin/sh sed '1 i\#!/bin/sh' sedswap.sh #在匹配到xxx行的前面一行插入Hello world sed '/xxx/i\Hello World' fileName #在匹配到xxx行的後面面一行插入Hello world sed '/xxx/a\Hello World' fileName
##sed命令拾遺spa
sed -e 's/pattern/& expect/' fileName echo "aaaHellobbb" | sed 's/Hello/ & World /' #結果:aaa Hello World bbb
sed -e 's/a/b/3' fileName #把第3個a替換爲b echo "aaaabbbb" | sed 's/a/x/3' #結果:aaxabbbb
#刪除不包含127.0.0.1的行 sed -e '/127.0.0.1/!d' fileName
# n 讀取下一行,這種在上一行是標籤,下一行是變量的時候比較經常使用 #由於沒有辦法匹配變量,因此匹配標籤,而後提取匹配到的下一行,例如 #username: #xxxx #由於姓名xxx不是固定的,很差匹配,直接匹配username:而後找下一行接容易多了 sed '/username:/n' -e 'p' fileName
###使用其它分隔符
#使用其它分隔符 #表示把全部Hello替換成Hello World。 sed 's#Hello#Hello World#g' fileName #不論什麼字符,緊跟着s命令的都被認爲是新的分隔符。 #因此,「#」在這裏是分隔符,代替了默認的「/」分隔符。
###使用()分組
#使用()分組 #思考:怎樣把aaatestbbb中的test提取出來呢?注意不是替換或者刪除, #是獲取,而且保存到hold space 以便於使用,這裏就能夠是用() #像其它正則表達式同樣,sed也可使用()進行分組 #這裏咱們利用分組來保存匹配,而後使用替換來把分組中的內容放到pattern space中 #而後使用h把pattern space中的內容拷貝到hold space中 echo "aaatestbbb" | sed 's/aaa\(test\)bbb/\1/' #一個()就表示一個分組,\1表示的第一分組,依次類推第二個分組\2,第三個分組\3 ··· #更加通常的表示 echo "aaatestbbb" | sed 's/.*\(test\).*/\1/' #放到hold space中 echo "aaatestbbb" | sed 's/.*\(test\).*/\1/;h;g'
###使用x交換pattern space 與 hold space 與pattern space 與 hold space存取相關的主要有4個命令,分別是g,G,h,H。能夠把g看作是get的嘛,就是用hold space中覆蓋pattern space。G是吧hold space中的內容追加到pattern space中。同理,h能夠看作是hold,表示用pattern space中的內容覆蓋hold space中。H表示把pattern space中的內容追加到hold space中。
#讓World Hello位置互換 echo "World Hello" | sed '/World/h;s/\(World\).*/\1/;x;s/.*\(Hello\)/\1/;G;s/\n/ /' #固然上面那個比較複雜了,下面來一個簡單的 echo "World Hello" | sed 's/\(World\)\(Hello\)/\2 \1/'
###使用r 和 w命令 r是讀文件的意思,在sed中就表示從文件中讀取內容插入到匹配行以後。仍是來一個具體的例子來講一下吧。好比有一個adv文件內容以下:
mylove文件內容以下:
an empty street
An empty house
A hole inside my heart
I'm all alone\n The rooms are getting smaller
I wonder how
I wonder why
執行下面的命令:
sed '/empty/r adv' mylove
結果以下:
an empty street
An empty house
A hole inside my heart
I'm all alone
The rooms are getting smaller
I wonder how
I wonder why
咱們能夠發現實在匹配到empty的行的後一行加了adv文件中的內容,咱們並無使用a命令。
w命令就是寫命令,在sed就是把匹配到的行寫入指定的文件中,咱們仍是使用上面的mylove文件,執行下面的命令:
sed '/empty/w result' mylove
執行完result文件中的內容爲:
an empty street
An empty house
咱們能夠看到把匹配到的2行寫入到了result文件中。
##sed的幾個命令選項
sed '1 i\#!/bin/sh' sedswap.sh sed -i '1 i\#!/bin/sh' sedswap.sh #對應上面2個命令看一下sedswap.sh文件就能夠發現執行完第一個命令只是 #輸出到標準輸出,sedswap.sh文件並無修改,而第2個命令, #沒有在標準輸出中輸出了,而是在sedswap.sh文件就添加了。
#若是一個命令的話-e能夠省略,例以下面2個命令就是同樣同樣的 sed '/xxx/a\Hello World' fileName sed -e '/xxx/a\Hello World' fileName #多個命令的話就要在每一命令前面都加上-e參數或者使用;分割 sed -e '/xxx/i\Hello World' -e '/xxx/a\Hello World' fileName #sed '/xxx/i\Hello World; /xxx/a\Hello World' fileName
這裏有一個誤區,不少資料說-n是隻輸出匹配行,實際上是不太準確的,-n就是不輸出,包括匹配到的都不輸出。能夠經過一個例子來驗證一下,假設num文件中的內容爲:
111111111
222222222
333333333
444444444
555555555
sed 's/333/xxx/' num #結果以下:
111111111
222222222
xxx333333
444444444
555555555
sed -n 's/333/xxx/' num #是沒有輸出的 sed -n 's/333/xxx/p' num #結果以下:
xxx333333
sed 's/333/xxx/p' num #結果以下:
111111111
222222222
xxx333333
xxx333333
444444444
555555555
從上面的結果來看,咱們能夠總結處理-n是不輸出,p(小p)是輸出匹配(sed處理的行),因此通常咱們-n參數和p命令結合起來使用,就只是輸出處理以後的結果。
這個選項一直沒有測試正確,不少資料也只是簡單說是執行sed腳本。其實這個命令是從指定的文件中讀取命令,不是腳本,只是sed命令,例如咱們要執行命令
sed 's/333/xxx/p' num
先在只須要把s/333/xxx/p寫入到一個文件中,這裏假設是command文件,接下來只須要執行下面的命令就能夠了:
sed -f command num
注意:文件中每一行是一個命令,命令不要加引號。 下面來一個更加具體的例子來講明一下,假設有一個文件word中的內容以下:
we have joy fun
we have joy in the sun
hello my trusted friend
command中的內容以下:
s/have/had/
a\append in the end
s/joy/joying/
執行下面的命令:
sed -f command word
結果以下:
we had joying fun
append in the end
we had joying in the sun
append in the end
hello my trusted friend
append in the end
##sed小結 注意sed是以行爲單位做爲處理和結果輸出的,你能夠把sed看作是一個簡單的編程語言,它按行來處理腳本。它可使用一個主內存pattern space和一個寄存器hold space。當你發現sed能夠完成一些難以想象的事情的時候,你就會理解那些大神的思惟是如此使人驚歎。