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
點選瞭解更多,快速檢視更多的技術文章列表。