鍍金池/ 教程/ Linux/ shell 學(xué)習(xí)第十天----sed 查找與替換
shell 學(xué)習(xí)四十一天----列出文件 ls 和 od 命令
shell 學(xué)習(xí)小結(jié)
shell 學(xué)習(xí)第二十八天----case 語(yǔ)句
shell 學(xué)習(xí)四十四天----尋找文件
shell 學(xué)習(xí)三十五天----波浪號(hào)展開(kāi)與通配符
shell 學(xué)習(xí)三十八天----執(zhí)行順序和 eval
shell 學(xué)習(xí)四十八天----文件校驗(yàn)和匹配
shell 學(xué)習(xí)四十天----awk 的驚人表現(xiàn)
shell 學(xué)習(xí)第十一天----sed 正則的精確控制
shell 學(xué)習(xí)第十七天----awk 命令
shell 學(xué)習(xí)三十九天----內(nèi)建命令
shell 學(xué)習(xí)四十五天----xargs
shell 學(xué)習(xí)三十七天----引用
shell 學(xué)習(xí)第十六天----join 練習(xí)
shell 學(xué)習(xí)第二十四天----提取開(kāi)頭或結(jié)尾數(shù)行
shell 學(xué)習(xí)第九天----分組
shell 學(xué)習(xí)第五天----基本的 I/O 重定向
shell 學(xué)習(xí)第十五天----使用 cut 選定字段
shell 學(xué)習(xí)四十六天----文件系統(tǒng)的空間信息 df 和 du 命令
shell 學(xué)習(xí)第八天----擴(kuò)展正則表達(dá)式 (ERE)
shell 學(xué)習(xí)第十九天----文本塊排序
shell 學(xué)習(xí)第二十一天----重新格式化段落
shell 學(xué)習(xí)三十六天----命令替換
shell 學(xué)習(xí)第二十天----sort 的其他內(nèi)容以及 uniq 命令
shell 學(xué)習(xí)四十二天----使用 touch 更新文件時(shí)間
shell 學(xué)習(xí)五十一天----top 命令查看進(jìn)程列表
shell 學(xué)習(xí)第一天
shell 學(xué)習(xí)五十四天----進(jìn)程系統(tǒng)調(diào)用的追蹤 strace
shell 學(xué)習(xí)五十天----查看進(jìn)程 ps 命令
shell 學(xué)習(xí)第二十七天----退出狀態(tài)和 if 語(yǔ)句
shell 學(xué)習(xí)第二十三天----打印
shell 學(xué)習(xí)三十三天----關(guān)于重定向
shell 學(xué)習(xí)四十九天----進(jìn)程建立
shell 學(xué)習(xí)第三十天----break,continue,shift,getopts
shell 學(xué)習(xí)五十五天----進(jìn)程記賬
shell 學(xué)習(xí)總結(jié)一
shell 學(xué)習(xí)第二十六天----變量與算數(shù)
shell 學(xué)習(xí)第二十二天----計(jì)算行數(shù), 字?jǐn)?shù)以及字符數(shù)
shell 學(xué)習(xí)五十八天----/proc 文件系統(tǒng)
shell 學(xué)習(xí)第二十五天----神器的管道符
shell 學(xué)習(xí)第三十二天----read 讀取一行
sheel 學(xué)習(xí)第三天
shell 學(xué)習(xí)----小結(jié)
shell 學(xué)習(xí)第十八天----文本排序
shell 學(xué)習(xí)第三十一天----函數(shù)問(wèn)題
shell 學(xué)習(xí)第十天----sed 查找與替換
shell 學(xué)習(xí)四十三天----臨時(shí)性文件的建立與使用
shell 學(xué)習(xí)四十七天----文件比較 cmp,diff,patch
shell 學(xué)習(xí)三十四天----printf 詳解
shell 學(xué)習(xí)五十七天 ----linux 任務(wù)管理,針對(duì)上一講的總結(jié)和擴(kuò)展
shell 學(xué)習(xí)第六天----小結(jié)
shell 學(xué)習(xí)第十三天----sed 案例分析
shell 學(xué)習(xí)第七天----基礎(chǔ)正則表達(dá)式 (BRE)
shell 學(xué)習(xí)第十二天----行與字符串
shell 學(xué)習(xí)小結(jié)四
shell 學(xué)習(xí)第二十九天----循環(huán)
shell 學(xué)習(xí)五十二天----刪除進(jìn)程 kill 命令
shell 學(xué)習(xí)五十六天----延遲進(jìn)程調(diào)度
shell 學(xué)習(xí)第四天----華麗的 printf 輸出
shell 學(xué)習(xí)第十五天----join 連接字段
shell 學(xué)習(xí)完結(jié)篇----希望你能看到
shell 學(xué)習(xí)第二天
shell 學(xué)習(xí)五十三天----捕獲信號(hào) trap

shell 學(xué)習(xí)第十天----sed 查找與替換

在文本文件離進(jìn)行替換

在很多 shell 腳本的工作都從通過(guò) grep 或 egrep 去除所需的文本開(kāi)始。 正則表達(dá)式查找的最初結(jié)果,往往就成了要拿來(lái)作進(jìn)一步處理的” 原始數(shù)據(jù)”。 通常,文本替換至少需要做一件事,就是講一些字以另一些字取代,或者刪除匹配行的某個(gè)部分。執(zhí)行文本替換的正確程序應(yīng)該是 sed----流編輯器。

sed 的設(shè)計(jì)就是用來(lái)批處理而不是交互的方式編輯文件。 當(dāng)藥做好幾個(gè)變化的時(shí)候,不管是對(duì)一個(gè)還是對(duì)數(shù)個(gè)文件,比較簡(jiǎn)單的方式就是將這些變更部分寫(xiě)到一個(gè)編輯的腳本里,再將此腳本應(yīng)用到所有必須修改的文件,sed 的存在目的就在這里。

在 shell 里,sed 主要用于一些簡(jiǎn)單的文本替換,所以我們先從他開(kāi)始。

基本用法:

我們經(jīng)常在管道中間使用 sed,用來(lái)執(zhí)行替換操作,做法是使用 s 命令 ---- 要求正則表達(dá)式尋找,用替換文本替換匹配的文本呢,以及可選的標(biāo)志:

  • sed ‘s’:.*//’ /etcpasswd | 刪除第一個(gè)冒號(hào)之后所有的東西
  • sort -u 排序列表并刪除重復(fù)部分

sed 的語(yǔ)法:

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

用途:

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

總合上述所言,當(dāng) sed 由標(biāo)準(zhǔn)輸入讀入一行資料并放入 pattern space 時(shí),sed 依照 sed script 的編輯指令逐一對(duì) pattern space 內(nèi)的資料執(zhí)行編輯,之後,再由 pattern space 內(nèi)的結(jié)果送到標(biāo)準(zhǔn)輸出,接著再將下一行資料讀入。 如此重執(zhí)行上述動(dòng)作,直至讀完所有資料行為止。

小結(jié)

記住:

  1. sed 總是以行對(duì)輸入進(jìn)行處理
  2. sed 處理的不是原文件而是原文件的拷貝

主要參數(shù):

  • -e: 執(zhí)行命令行中的指令,例如:sed -e 'command' file(s)
  • -f: 執(zhí)行一個(gè) sed 腳本文件中的指令,例如: sed -f scriptfile file(s)
  • -i: 與 -e 的區(qū)別在于:當(dāng)使用 -e 時(shí),sed 執(zhí)行指令并不會(huì)修改原輸入文件的內(nèi)容,只會(huì)顯示在 bash 中,而使用 -i 選項(xiàng)時(shí),sed 執(zhí)行的指令會(huì)直接修改原輸入文件。
  • -n: 讀取下一行到 pattern space。

行為模式

讀取輸入文件的每一行。 假如沒(méi)有文件的話(huà),則是標(biāo)準(zhǔn)輸入。 以每一行來(lái)說(shuō),sed 會(huì)執(zhí)行每一個(gè)應(yīng)用倒數(shù)入行的 esiting command。 結(jié)果會(huì)寫(xiě)到標(biāo)準(zhǔn)輸出 (默認(rèn)情況下,或是顯式的使用 p 命令及 -n 選項(xiàng))。 若無(wú) -e 或 -f 選項(xiàng),則 sed 會(huì)把第一個(gè)參數(shù)看做是要使用的 editing command。

  • find /home/tolstoy -type -d -print // 尋找所有目錄
  • sed ‘s;/home/tolstor;/home/lt/;’ // 修改名稱(chēng); 注意: 這里使用分號(hào)作為定界符
  • sed ‘s/^/mkdir /’ // 插入 mkdir 命令
  • sh -x // 以 shell 跟蹤模式執(zhí)行

上述腳本是說(shuō)將 /home/tolstoy 目錄結(jié)構(gòu)建立一份副本在 /home.lt 下 (可能是為備份) 而做的準(zhǔn)備

替換案例

Sed 可替換文件中的字串、資料行、甚至資料區(qū)。其中,表示替換字串的指令中的函數(shù)參數(shù)為 s; 表示替換資料行、或資料區(qū) > 的指令中的函數(shù)參數(shù)為 c。上述情況以下面三個(gè)例子說(shuō)明。

* 行的替換

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----- 在整行范圍內(nèi)把 test 替換為 mytest。如果沒(méi)有 g 標(biāo)記,則只有每行第一個(gè)匹配的 test 被替換成 mytest。
  • $ sed -n 's/^test/mytest/p' example-----(-n) 選項(xiàng)和 p 標(biāo)志一起使用表示只打印那些發(fā)生替換的行。也就是說(shuō),如果某一行開(kāi)頭的 test 被替換成 mytest,就打印它。
  • $ sed 's/^192.168.0.1/&localhost/' example-----& 符號(hào)表示替換換字符串中被找到的部份。所有以 192.168.0.1 開(kāi)頭的行都會(huì)被替換成它自已加 localhost,變成 192.168.0.1localhost。
  • $ sed -n 's/loveable/\1rs/p' example-----love 被標(biāo)記為 1,所有 loveable 會(huì)被替換成 lovers,而且替換的行會(huì)被打印出來(lái)。
  • $ sed 's#10#100#g' example----- 不論什么字符,緊跟著 s 命令的都被認(rèn)為是新的分隔符,所以,“#” 在這里是分隔符,代替了默認(rèn)的 “/” 分隔符。表示把所有 10 替換成 100。

替換與查找

在 s 命令里以 g 結(jié)尾表示的是: 全局性,意即” 替代文本取代正則表達(dá)式中每一個(gè)匹配的”。 如果沒(méi)有設(shè)置 gsed 指揮取代第一個(gè)匹配的。

鮮為人知的是: 可以在結(jié)尾指定數(shù)字,只是第 n 個(gè)匹配出現(xiàn)才要被取代:

  • sed ‘s/Tom/Lisy/2’ < Test.txt 僅匹配第二個(gè) Tom 通過(guò)給 sed 增加一個(gè) -e 選項(xiàng)的方式能讓 sed 接受多個(gè)命令。
  • sed -e ‘s/foo/bar/g’ -e ‘s/chicken/cow/g’ myfile.txt 1>myfile2.txt 用 shell 命令將 test.log 文件中第 3-5 行的第 2 個(gè)“filter” 替換成“haha”
  • sed -i '3,5s/filter/haha/2' test.log