Linux sed 詳解

##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正則

##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

& 引用pattern匹配到的字符串

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 獲取匹配下一行

# 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文件內容以下:

http://www.freemethod.cn

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

http://www.freemethod.cn

An empty house

http://www.freemethod.cn

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的幾個命令選項

-i選項,表示直接在文件中修改

sed '1 i\#!/bin/sh' sedswap.sh

sed -i '1 i\#!/bin/sh' sedswap.sh
#對應上面2個命令看一下sedswap.sh文件就能夠發現執行完第一個命令只是
#輸出到標準輸出,sedswap.sh文件並無修改,而第2個命令,
#沒有在標準輸出中輸出了,而是在sedswap.sh文件就添加了。

-e選項 -e選項後面直接跟一個完整的命令

#若是一個命令的話-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是隻輸出匹配行,實際上是不太準確的,-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命令結合起來使用,就只是輸出處理以後的結果。

-f選項 從文件中讀取命令

這個選項一直沒有測試正確,不少資料也只是簡單說是執行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能夠完成一些難以想象的事情的時候,你就會理解那些大神的思惟是如此使人驚歎。

相關文章
相關標籤/搜索