sed使用整理

-------------sed 查找與替換----------------

在文本文件離進行替換

在很多 shell 腳本的工作都從通過 grep 或 egrep 去除所需的文本開始。正則表達式查找的最初結果,往往就成了要拿來作進一步處理的“原始數據”。通常,文本替換至少需要做一件事,就是講一些字以另一些字取代,或者刪除匹配行的某個部分。

執行文本替換的正確程序應該是 sed----流編輯器。

sed 的設計就是用來批處理而不是交互的方式編輯文件。當藥做好幾個變化的時候,不管是對一個還是對數個文件,比較簡單的方式就是將這些變更部分寫到一個編輯的腳本里,再將此腳本應用到所有必須修改的文件,sed 的存在目的就在這裏。

在 shell 裏,sed 主要用於一些簡單的文本替換,所以我們先從他開始。

基本用法:我們經常在管道中間使用 sed,用來執行替換操作,做法是使用 s 命令----要求正則表達式尋找,用替換文本替換匹配的文本呢,以及可選的標誌:

sed ‘s’:.*//’ /etcpasswd | 刪除第一個冒號之後所有的東西

sort -u 排序列表並刪除重複部分

sed的語法:

sed [-n] ‘editing command’ [file...]

sed [-n] -e ‘editing command’ [file...]

sed [-n] -f script-file... [file...]

用途: sed 可刪除(delete)、改變(change)、添加(append)、插入(insert)、合、交換文件中的資料行,或讀入其它檔的資料到文>件中,也可替換(substuite)它們其中的字串、或轉換(tranfer)其中的字母等等。例如將文件中的連續空白行刪成一行、"local"字串替換成"remote"、"t"字母轉換成"T"、將第 10 行資料與第 11 資料合等。

總合上述所言,當 sed 由標準輸入讀入一行資料並放入 pattern space 時,sed 依照 sed script 的編輯指令逐一對 pattern space 內的資料執行編輯之後,再由 pattern space 內的結果送到標準輸出,接着再將下一行資料讀入。如此重執行上述動作,直至讀完所有資料行爲止。

小結,記住:

(1)sed 總是以行對輸入進行處理

(2)sed 處理的不是原文件而是原文件的拷貝


主要參數:

-e:執行命令行中的指令,例如:sed -e 'command' file(s)

-f:執行一個 sed 腳本文件中的指令,例如: sed -f scriptfile file(s)

-i:與-e的區別在於:當使用-e 時,sed 執行指令並不會修改原輸入文件的內容,只會顯示在 bash 中,而使用-i 選項時,sed 執行的指令會直接修改原輸入文件。

-n:讀取下一行到 pattern space。

行爲模式:

讀取輸入文件的每一行。假如沒有文件的話,則是標準輸入。以每一行來說,sed 會執行每一個應用倒數入行的 esiting command。結果會寫到標準輸出(默認情況下,或是顯式的使用 p 命令及-n 選項)。若無-e 或-f 選項,則 sed 會把第一個參數看做是要使用的 editing command。


find  /home/tolstoy  -type -d -print // 尋找所有目錄  

sed ‘s;/home/tolstor;/home/lt/;’ // 修改名稱;注意:這裏使用分號作爲定界符  

sed ‘s/^/mkdir /’ `//插入 mkdir 命令  

sh -x`                           //以 shell 跟蹤模式執行

上述腳本是說將/home/tolstoy 目錄結構建立一份副本在/home.lt 下(可能是爲備份)而做的準備


替換案例:

Sed 可替換文件中的字串、資料行、甚至資料區。其中,表示替換字串的指令中的函數參數爲s;表示替換資料行、或資料區>的指令中的函數參數爲c。上述情況以下面三個例子說明。


行的替換

sed -e '1c/#!/bin/more' file (把第一行替換成#!/bin/more)

思考:把第 n 行替換成 just do it

sed -e 'nc/just do it' file

sed -e '1,10c/I can do it' file (把 1 到 10 行替換成一行: I can do it)

思考:換成兩行(I can do it! Let's start)

sed -e '1,10c/I can do it!/nLet'"/'"'s start' file

字符的替換

$ sed 's/test/mytest/g' example-----在整行範圍內把 test 替換爲 mytest。如果沒有 g 標記,則只有每行第一個匹配的 test 被替換成 mytest。

$ sed -n 's/^test/mytest/p' example-----(-n)選項和 p 標誌一起使用表示只打印那些發生替換的行。也就是說,如果某一行開頭的 test 被替換成 mytest,就打印它。

$ sed 's/^192.168.0.1/&localhost/' example-----&符號表示替換換字符串中被找到的部份。所有以 192.168.0.1 開頭的行都會被替換成它自已加 localhost,變成 192.168.0.1localhost。

$ sed -n 's/loveable/\1rs/p' example-----love 被標記爲 1,所有 loveable 會被替換成 lovers,而且替換的行會被打印出來。

$ sed 's#10#100#g' example-----不論什麼字符,緊跟着 s 命令的都被認爲是新的分隔符,所以,“#”在這裏是分隔符,代替了默認的“/”分隔符。表示把所有 10 替換成 100。


替換與查找

在 s 命令裏以 g 結尾表示的是:全局性,意即“替代文本取代正則表達式中每一個匹配的”。如果沒有設置 gsed 指揮取代第一個匹配的。


鮮爲人知的是:可以在結尾指定數字,只是第 n 個匹配出現纔要被取代:

sed ‘s/Tom/Lisy/2’ < Test.txt 僅匹配第二個 Tom

通過給 sed 增加一個-e 選項的方式能讓 sed 接受多個命令。

sed -e ‘s/foo/bar/g’ -e ‘s/chicken/cow/g’ myfile.txt 1>myfile2.txt

用 shell 命令將 test.log 文件中第 3-5 行的第 2 個“filter”替換成“haha”

sed -i '3,5s/filter/haha/2' test.log


下面介紹所有 sed 的函數參數的功能(editing command)。

= 印出資料行數( line number )。


a :添加使用者輸入的資料。

b :label 將執行的指令跳至由 : 建立的參考位置。

c :以使用者輸入的資料取代資料。

d :刪除資料。

D :刪除 pattern space 內第一個 newline 字母 前的資料。

g :拷貝資料從 hold space。

G :添加資料從 hold space 至 pattern space 。

h :拷貝資料從 pattern space 至 hold space 。

H :添加資料從 pattern space 至 hold space 。

l :印出 l 資料中的 nonprinting character 用 ASCII 碼。

i :插入添加使用者輸入的資料行。

n :讀入下一筆資料。

N :添加下一筆資料到 pattern space。

p :印出資料。

P :印出 pattern space 內第一個 newline 字母 前的資料。

q :跳出 sed 編輯。

r :讀入它檔內容。

s :替換字串。

w :寫資料到它檔內。

x :交換 hold space 與 pattern space 內容。

y :轉換(transform)字元。


---sed 正則的精確控制----------

有多少文本會改動

在使用 sed 的時候我們來看這麼兩個問題:第一個問題是有多少人文本會匹配,第二個問題是從哪裏開始匹配。

回答是:正則表達式可以匹配整個表達式的輸入文本中最長的,最左邊的子字符串。除此之外,匹配的空(null)字符串,則被認爲是比完全不匹配的還長.

echo syx is a good body | sed ‘s/syx/zsf/’ 使用固定字符串

sed 可以使用完整的正則表達式.但是應該知道”從最長的最左邊”規則的重要性.


echo Tolstoy is worldly | sed ‘s/T.*y/Camus/’

Camus

很明顯,我們只想要匹配 Tolstoy,但是由於匹配會擴展到可能的最長長度的文本量,所以出現了這樣的結果.


這就需要我們精確定義:

echo Tolstoy is worldly | sed ‘s/T[[:alpha:]]*y/Camus/’

Camus is worldly

在文本查找中,有事喊可能會匹配到 null 字符串,而在執行文本替代時,也允許插入文本.


ehco abc | sed ‘s/b*/l/’ 

labc  

ehco abc | sed ‘s/b*/l/g’  

lalcl  

請留意,b*shi 如何匹配 abc 的前面與結尾的 null 字符串.


------行與字符串-------

行 V.S.字符串

大部分建議等程序都是處理輸入數據的行,在這些情況下,不會有內嵌的換行字符出現在將要匹配的數據中,^與$則分別表示行的開頭與結尾.


很多應用程序會將數據是位記錄與字段的結合.一條記錄指的是相關信息的翻個集合,例如以企業來說,記錄可能含有顧客,供應商以及員工等數據,以學校來說,則可能有學生數據.而字段指的就是記錄的組成部分,例如姓名或者街道地址.


linux 鼓勵使用文本類型數據,因此係統上最常見的數據存儲類型就是文本了,在文本下,一行表示一天記錄.一行內分割字段的兩種慣例是:

第一種:空格或者 tab 鍵(製表符).

name sex

syx M

第二種是使用特定的定界符來分割字段,例如冒號

name:sex

syx:M

兩種方式各有優缺點.最明顯的不同時是在處理多個連續重複的戒定福之時.使用空白分隔時,通常多個連續出現的空格或製表字符都看做一個定界符.濡染,若使用的特殊字符分隔,則每個定界符都會隔開一個字段.


以定界符分割字段最好的例子就是/etc/passwd,在這個文件裏,一行標識系統的一個用戶,每個字段都是以冒號分隔.


syx5:x:511:513::/home/syx5:/bin/bash.


該文件含有七個字段,含義分別如下


1:用戶名稱

2:加密後的密碼(如賬號爲停用狀態,此處爲一個星號,或者若加密後的密碼 文件存儲於另外的/etc/shadow 裏,則這裏可能是其他字符)

3:用戶的 ID 編號

4:用戶組的 ID 編號

5:用戶的姓名,有時恢復其他的相關數據(電話號,辦公室號碼)

6:根目錄

7:登陸的 shell


-----------sed 案例分析------------------

sed 的使用案例

使用 sed 操作/etc/passwd,最好複製一份(cp /etc/passwd /tmp),操作 tmp 下的 passwd(其實不用,因爲在一般情況下 sed 只是修改了輸出結果,不會改變文件本身,除非要求這麼做).


以行爲單位的新增/刪除

要求:將/etc/passwd 的內容列出並且列印行號,同時刪除 2~5 行.

做法:cat /etc/passwd | sed ‘2,5d’

sed 的動作是’2,5d’(動作需要放在單引號之間)

nl 命令在 linux 系統中用來計算文件中行號。nl 可以將輸出的文件內容自動的加上行號!其默認的結果與 cat -n 有點不太一樣, nl 可以將行號做比較多的顯示設計,包括位數與是否自動補齊 0 等等的功能。

只刪除第二行:

nl /etc/passwd | sed ‘2d’


刪除第3行到最後一行

cat -n /etc/passwd | sed ‘3,$d’


在第二行後(就是在第三行)加上”i am fine”字樣

cat -n /etc/passwd | sed ‘2a i am fine’


如果要在第二行前面

nl /etc/passwd | sed ‘2i i am fine’


如果是要增加兩行以上,在第二行後面加入兩行字,例如『hello』與『how are you』

nl /etc/passwd | sed ‘2a hello\

>how are you’

每一行之間都必須要以反斜槓()來進行新行的添加,所以上面的例子,我們可以發現在第一行的最後面就有 \ 存在。

(再輸入的是會需要注意,單引號不要一起輸完).


以行爲單位的替換與現實

將第 2-5 行的內容替換成”hahaha”

nl /etc/passwd | sed ‘2,5c hahaha’

通過這個方法,我們就可以替換整行數據了.


僅列出/etc/passwd 文件的 5-7 行

cat -n /etc/passwd | sed -n ‘5,7p’

可以透過這個 sed 的以行爲單位的顯示功能, 就能夠將某一個文件內的某些行號選擇出來顯示。


數據的搜尋與顯示

搜索/etc/passwd 中有關/root 關鍵字的行

nl /etc/passwd | sed ‘/root/p’

思考:爲什麼會輸出所有行的情況?

使用-n 的時候將只打印包含模板的行。

nl /etc/passwd | sed -n ‘/root/p’


數據的搜索與刪除

刪除/etc/passwd 所有包含 root 的行,其他行輸出

nl /etc/passwd | sed ‘/root/d’


數據的搜索並執行命令

搜索/etc/passwd,找到 root 對應的行,執行後面花括號中的一組命令,每個命令之間用分號分隔,這裏把 bash 替換爲 blueshell,再輸出這行:

nl /etc/passwd | sed -n '/root/{s/bash/blueshell/;p}'

如果只替換/etc/passwd 的第一個 bash 關鍵字爲 blueshell,就退出

nl /etc/passwd | sed -n '/bash/{s/bash/blueshell/;p;q}' 1

最後的 q 是退出。


數據的搜索並替換

除了整行的處理模式之外,sed 還可以用行爲單位進行部分數據的搜尋並替換.基本上 sed 的搜尋與替換與 vi 相當的類似.

sed ‘s/要被取代的字符串/新的字符串/g’


先通過/sbin/ifconfig eth0 查看本機的 IP 地址,我的是(192.168.199.5)

將 IP 前面部分予以刪除

/sbin/ifconfig eth0 | grep 'inet addr'|sed 's/^.*addr://g'

將 IP 後面部分予以刪除

/sbin/ifconfig eth0 | grep 'inet addr'|sed 's/^.*addr://g' | sed 's/Bcast.*$//g'

即可得到 IP


多點編輯

一條 sed 命令,刪除/etc/passwd 第三行到末尾的數據,並把 bash 替換成 hahaha.

nl /etc/passwd | sed -e ‘3,$d’ -e ‘s/bash/hahaha/g’

注意:每天命令前面都加入了-e 選項


直接修改文件內容

最好別使用,如果使用需要加入一個-i 選項

例如在最後一行插入 hahaha


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章