Linux如何批量替換文字檔案內容

請關注本頭條號,每天堅持更新原創乾貨技術文章。

如需學習視訊,請在微信搜尋公眾號“智傳網優”直接開始自助視訊學習

1. 前言

sed全名叫stream editor,流編輯器,用程式的方式來編輯文字,它一次處理一行內容。處理時,把當前處理的行儲存在臨時緩衝區中,稱為“模式空間”(pattern space),接著用sed命令處理模式空間中的內容,處理完成後,把緩衝區的內容送往螢幕。接著處理下一行,這樣不斷重複,直到檔案末尾。檔案內容並沒有改變,因為這些都在模式空間處理的。Sed可以用來自動編輯一個或多個檔案。

Linux批量替換檔案內容

普及一下正規表示式的一些基本知識:

^ 表示一行的開頭。如:/^#/ 以#開頭的匹配。

不能識別此Latex公式:  表示一行的結尾。如:/}    

/ 以}結尾的匹配。

< 表示詞首。 如:<abc 表示以 abc 為首的詞。

/> 表示詞尾。 如:abc/> 表示以 abc 結尾的詞。

. 表示任何單個字元。

  • 表示某個字元出現了0次或多次。
  • [ ] 字符集合。 如:[abc] 表示匹配a或b或c,還有 [a-zA-Z] 表示匹配所有的26個字元。如果其中有^表示反,如 [a] 表示非a的字元

2. sed命令選項

-n :使用安靜(silent)模式。在一般 sed 的用法中,所有來自 STDIN 的資料一般都會被列出到終端上。但如果加上 -n 引數後,則只有經過sed 特殊處理的那一行(或者動作)才會被列出來。

-e :直接在命令列模式上進行 sed 的動作編輯;

-f :直接將 sed 的動作寫在一個檔案內, -f filename 則可以執行 filename 內的 sed 動作;

-r :sed 的動作支援的是延伸型正規表示法的語法。(預設是基礎正規表示法語法)

-i :直接修改讀取的檔案內容,而不是輸出到終端。

動作說明: [n1[,n2]]function

n1, n2 :不見得會存在,一般代表『選擇進行動作的行數』,舉例來說,如果我的動作是需要在 10 到 20 行之間進行的,則『 10,20[動作行為] 』

function:

a/ 在當前行下面插入文字。

i/ 在當前行上面插入文字。

c/ 把選定的行改為新的文字。

d 刪除,刪除選擇的行。

D 刪除模板塊的第一行。

s 替換指定字元

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 寫並追加模板塊到file末尾。

W file 寫並追加模板塊的第一行到file末尾。

! 表示後面的命令對所有沒有被選定的行發生作用。

= 列印當前行號碼。

# 把註釋擴充套件到下一個換行符以前。

Linux sed命令詳解

3. 測試檔案說明

複製/etc/passwd到~/zcwyou.txt

[root@zcwyou ~]# cp /etc/passwd ~/zcwyou.txt    

下文以zcwyou.txt作說明。

4. 使用sed刪除輸出結果某些行

列印zcwyou.txt的內容並附帶行號,不顯示3-7行

[root@zcwyou ~]# nl ~/zcwyou.txt | sed '3,7d'    

sed 的動作為 '3,7d' ,d表示刪除。同時也要注意的是, sed 後面接的動作,請務必以 '' 兩個單引號括住喔!

5. 刪除特定的行

把輸出結果刪除第2行。

[root@zcwyou ~]# nl ~/zcwyou.txt | sed '2d'    

刪除帶有123的行:

[root@zcwyou ~]# sed '/123/d' zcwyou.txt    

刪除第二行

[root@zcwyou ~]# sed '2d' zcwyou.txt    

刪除第2行到最後一行。

[root@zcwyou ~]# sed '2,$d' zcwyou.txt    

6. 從某行開始刪除

要刪除第 3 到最後一行

[root@zcwyou ~]# nl ~/zcwyou.txt | sed '3,$d'    

7. 使用sed新增行

在第二行後面加上字串hello jack

[root@zcwyou ~]# nl ~/zcwyou.txt | sed '2a hello jack'    

在第二行前面加上字串hello jack

[root@zcwyou ~]# nl ~/zcwyou.txt | sed '2i hello jack'    

以行為單位的替換與顯示

將第2-5行的內容取代成為Line2-5

[root@zcwyou ~]# nl ~/zcwyou.txt | sed '2,5c Line2-5'    

8. 根據條件僅列出某些行

僅列出 ~/zcwyou.txt 檔案內的第 5-7 行

[root@zcwyou ~]# nl ~/zcwyou.txt | sed -n '5,7p'    

9. 使用sed查詢資料

列印~/zcwyou.txt的內容,查詢帶root的行並列印2次。

[root@zcwyou ~]# nl ~/zcwyou.txt | sed '/root/p'    

如果root找到,除了輸出所有行,還會輸出匹配行。

[root@zcwyou ~]# nl ~/zcwyou.txt | sed -n '/root/p'    

檢視關鍵詞並刪除

刪除~/zcwyou.txt所有包含root的行,輸出其他內容

[root@zcwyou ~]# nl ~/zcwyou.txt | sed '/root/d'    

10. 檢視關鍵詞並執行命令

搜尋~/zcwyou.txt,找到root對應的行,執行後面花括號中的一組命令,每個命令之間用分號分隔,這裡把bash替換為abcshell,再輸出這行:

[root@zcwyou ~]# nl ~/zcwyou.txt | sed -n '/root/{s/bash/abcshell/;p}'    

如果只替換~/zcwyou.txt的第一個bash關鍵字為abcshell,完成後自動退出

[root@zcwyou ~]# nl ~/zcwyou.txt | sed -n '/bash/{s/bash/abcshell/;p;q}'    

11. 列印奇數行或偶數行

方法1:

奇數行

[root@zcwyou ~]# sed -n 'p;n' zcwyou.txt    

偶數行

[root@zcwyou ~]# sed -n 'n;p' zcwyou.txt    

方法2:

奇數行

[root@zcwyou ~]# sed -n '1~2p' zcwyou.txt    

偶數行

[root@zcwyou ~]# sed -n '2~2p' zcwyou.txt    

列印匹配字串的下一行

[root@zcwyou ~]# grep -A 1 SCC zcwyou.txt [root@zcwyou ~]# sed -n '/SCC/{n;p}' zcwyou.txt [root@zcwyou ~]# awk '/SCC/{getline; print}' zcwyou.txt    

12. 查詢關鍵詞並替換

格式:

sed 's/要被取代的字串/新的字串/g'

先看看現有的樣版檔案內容:

[root@zcwyou ~]# cat sshforwarding.service    

輸出結果:

[Unit]

Description=SSH Forward TCP Port 9001 To SS Server

Documentation=https://linux.die.net/man/1/ssh

After=network.target remote-fs.target nss-lookup.target

[Service]

Type=forking

ExecStart=/usr/bin/ssh -NT -f -L my_public_ip:9001:SS_server:9001 localhost

ExecReload=/bin/kill -HUP

MAINPID

[Install]

WantedBy=multi-user.target

要求把以上文字中的9001替換為9002

替換命令:

[root@zcwyou ~]# sed "s/9001/9002/g" sshforwarding.service    

輸出結果:

[Unit]

Description=SSH Forward TCP Port 9002 To Shadowsocks Server

Documentation=https://linux.die.net/man/1/ssh

After=network.target remote-fs.target nss-lookup.target

[Service]

Type=forking

ExecStart=/usr/bin/ssh -NT -f -L my_public_ip:9002:shadowsocks_server:9002 localhost

ExecReload=/bin/kill -HUP

MAINPID

[Install]

WantedBy=multi-user.target

可以看到,9001已經被換為9002,但這樣並沒有修改原始檔,也沒有儲存為新檔案,我們需要把它重定向儲存為新檔案。

替換後儲存為新檔案:

[root@zcwyou ~]# sed "s/9001/9002/g" sshforwarding.service > sshforwarding9002.service    

這樣就可以儲存為新檔案sshforwarding9002.service

如果只替換第4到第8行的文字內容,命令如下:

[root@zcwyou ~]# sed "4,8s/9001/9002/g" zcwyou.txt    

只替換每一行的第一個abc:

[root@zcwyou ~]# sed 's/abc/S/1' zcwyou.txt    

只替換每一行的第二個abc:

[root@zcwyou ~]# sed 's/abc/S/2' zcwyou.txt    

只替換第一行的第3個以後的abc:

[root@zcwyou ~]# sed 's/abc/S/3g' zcwyou.txt    

13. 替換匹配行

使用選項c

把zcwyou.txt的第二行替換為line 2

[root@zcwyou ~]# sed "2 c line 2" zcwyou.txt    

檢視帶有abc的行,替換內容為line hahaha

[root@zcwyou ~]# sed "/abc/c line hahaha" zcwyou.txt    

sed替換標記

linux sed 替換字串

g 表示行內全面替換。

p 表示列印行。

w 表示把行寫入一個檔案。

x 表示互換模板塊中的文字和緩衝區中的文字。

y 表示把一個字元翻譯為另外的字元(但是不用於正規表示式)

/1 子串匹配標記

& 已匹配字串標記

14. sed同時執行多工

一條sed命令,刪除~/zcwyou.txt第三行到末尾的資料,並把bash替換為abcshell

[root@zcwyou ~]# nl ~/zcwyou.txt | sed -e '3,$d' -e 's/bash/abcshell/'    

-e表示多點編輯,第一個動作是刪除~/zcwyou.txt第三行到末尾的資料,第二條命令搜尋bash替換為abcshell。

15. 使用sed直接修改檔案內容(危險不建議)

sed 可以直接修改檔案的內容,不必使用管道命令或資料流重導向! 不過,由於這個動作會直接修改到原始的檔案,所以建議找一個無用的檔案做測試,比如本文裡的zcwyou.txt,僅僅用來實驗研究。

利用sed將zcwyou.txt內的每一行結尾a換成b

[root@zcwyou ~]# sed -i 's/a$/b/g' zcwyou.txt    

利用 sed 直接在zcwyou.txt 最後一行加入字元end

[root@zcwyou ~]# sed -i '$a end' zcwyou.txt    

$代表的是檔案最後一行,而a表示新增內容,因此執行結果是使該檔案最後一行新增字元end。不要忘記了,該方法是直接修改原始檔,除非你清楚清楚後果,強烈建議使用副本修改並確認無誤後才覆蓋線上的配置環境。

sed的-i選項非常實用,特別是遇到大檔案要修改時,如果你使用vi或vim修改,效率將會非常低。而使用sed,它會自動查詢並按要求完成,非常處理速度極為迅速,幾乎沒有等待。

本文已同步至部落格站,尊重原創,轉載時請在正文中附帶以下連結:

https://www.linuxrumen.com/cyml/852.html

點選瞭解更多,快速檢視更多的技術文章列表。