Linux sed 字串取代用法與範例

本篇 ShengYu 將介紹如何使用 Linux 下的 sed 指令來取代/替換字串,相同地 sed 指令也可以在 macOS 下做字串取代,但有些情形需要一些改動詳見下面內容,平時在寫 Shell Script 時經常會使用到 sed 取代字串,由於 sed 這強大指令博大精深,又很容易忘記,所以在這邊會記錄一下我常用到的功能。

以下的 Linux sed 用法與範例將分為這幾部分,

  • Linux sed 基本用法
  • Linux sed 常用範例
  • find 指令找到檔案後 pipe 給 sed 取代文字
  • grep 指令搜尋內容符合的檔案 pipe 給 sed 取代文字
  • shell script 中 find 找檔案後傳給 sed 指令
  • shell script 中傳變數給 sed 指令
  • sed 刪除符合特定字樣的那些行
  • sed 轉換 hex string 成 byte string

那我們開始吧!

Linux sed 基本用法

這邊介紹 Linux sed 基本用法,假設我們要將設定檔裡某變數 : 冒號之後的任意字串取代掉,
今天有份 settings.conf 設定檔如下,

settings.conf
1
2
name: Alan
age: 18

情況1. 希望將裡面的在 settings.conf 裡取代所有的 Alan 字串, 替換成 Barry

1
$ sed -i 's/Alan/Barry/g' settings.conf

情況2. 將 name: 後面的任何字元取代成 name: Duke

1
$ sed -i 's/name:.*/name: Duke/g' settings.conf

同樣的指令在 macOS 下要修改一下,在 -i 後面多加一個內容為空 "" 的參數,
否則會出現 unterminated substitute pattern。

1
$ sed -i "" 's/name:.*/name: Duke/g' settings.conf

但是如果沒有使用 -i 的參數的話 Linux 與 macOS 使用的指令則相同,例如 sed 's/name:.*/name: Duke/g' settings.conf ,但是使用 -i 才會將結果寫回原本的檔案。

Linux sed 常用範例

以下為 Linux sed 常用範例,搜尋的字串如果內含空白的話,則空白前要加反斜線 \

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 單檔取代, oldtext取代成newtext
$ sed -i 's/oldtext/newtext/g' <filename>

# 對當前目錄下所有的txt副檔名, oldtext取代成newtext
$ sed -i 's/oldtext/newtext/g' *.txt

# 取代有含空白的字串,abc d取代成a bcd
$ sed -i 's/abc\ d/a\ bcd/g' <filename>

# 取代 `http` 開頭的
# http://xxx.com/index.html -> https://xxx.com/index.html
$ sed -i 's/^http/https/g' <filename> # 將所有在行首的http字串替換成https,如果http不是在行首的字串,則不會被取代掉

# 取代 com. 結尾的
# https://xxx.com/index.html -> https://xxx.edu
$ sed -i 's/com.*/edu/g' <filename> # 將所有 "com.後面接任意字元任意長度" 的字串替換成 edu

# 刪除行首空格
$ sed 's/^[ \t]*//g'

# 刪除行末空格
$ sed 's/[ \t]*$//g'

find 指令找到檔案後 pipe 給 sed 取代文字

find 指令找到檔案後 pipe 給 sed 取代文字的方式如下,範例內容是假設我要找的檔案類型是 txt 副檔名,用 find 把所有 txt 副檔名找出來後將這些檔案名稱 pipe 給 sed 取代文字,將這些檔案裡的 http 全部取代成 https,

1
2
3
4
# Linux
find ./ -iname "*.txt" -type f | xargs sed -i 's/http/https/g'
# macOS
find ./ -iname "*.txt" -type f | xargs sed -i "" 's/http/https/g'

grep 指令搜尋內容符合的檔案 pipe 給 sed 取代文字

grep 指令搜尋內容符合的檔案 pipe 給 sed 取代文字的方式如下,範例內容是假設我要搜尋檔案內容有 http 的字串找出來後將這些檔案名稱 pipe 給 sed 取代文字,將這些檔案裡的 http 全部取代成 https,

1
2
3
4
# Linux
grep -ri "http" * -l | xargs sed -i 's/http/https/g'
# macOS
grep -ri "http" * -l | xargs sed -i "" 's/http/https/g'

如果 grep 換成 ag 的話,

1
2
3
4
# Linux
ag "http" -l | xargs sed -i 's/http/https/g'
# macOS
ag "http" -l | xargs sed -i "" 's/http/https/g'

shell script 中 find 找檔案後傳給 sed 指令

假如寫成 shell script 時,想要將變數帶進 sed 的參數裡的話,會發現剛剛上述的例子的 's/$1/$2/g' 單引號(single quotes)方式會失效,無法將 shell script 變數取值出來,這是因為要用雙引號(double quotes)的方式才能將 shell script 變數取值,所以就要改成 "s/$1/$2/g" 這樣的方式,如下範例中的 replace_http 函式,

1
2
3
4
5
function replace_http() {
find ./ -iname "*.txt" -type f | xargs sed -i "s/$1/$2/g"
}

replace_http "http" "https"

shell script 中傳變數給 sed 指令

在 shell script 要傳變數給 sed 處理的話,可以這樣寫,
以下範例是用 sed 將 abcabc 字串裡的 a 換成 z,

1
2
STR=abcabc
echo $STR | sed 's/a/z/g'

結果為

1
zbczbc

sed 刪除符合特定字樣的那些行

以下範例是刪除 settings.conf 中符合 text 字樣的那些行,所以 settings.conf 裡有 3 行都符合的話就會刪除那 3 行,

1
sed -i '/text/d' settings.conf

在 shell script 中寫成變數的話 sed 就要改用雙引號才能取得變數的字串數值,

1
2
PATTERN="text"
sed -i "/$PATTERN/d" settings.conf

PATTERN 中出現特殊字元的話,我自己的經驗是 sed 在遇到左中括號 [ 會需要跳脫字元否則有機率會出錯,解決方式為在 PATTERN 裡的所有左中括號 [ 前插入跳脫字元,

1
2
3
PATTERN="[2020-12-11]"
PATTERN2=`echo "$PATTERN" | sed 's/\[/\\\[/g'`
sed -i "/$PATTERN2/d" settings.conf

在 stackexchange 這篇有一些討論左中括號 [ 會需要跳脫字元的討論。

sed 轉換 hex string 成 byte string

如果想要將 00123a4b 的 hex 字串 \x00\x12\x3a\x4b 轉成 byte 字串的話,可以透過 sed 來達成,sed 指令如下,

1
2
$ echo "00123a4b" | sed 's/../\\x&/g'
\x00\x12\x3a\x4b

如果是要將 00123a4b 的 hex 字串 0x00, 0x12, 0x3a, 0x4b, 轉成逗號間隔的話,就這樣使用,

1
2
$ echo "00123a4b" | sed 's/../0x&, /g'
0x00, 0x12, 0x3a, 0x4b,

參考
sed @ 工作筆記 :: 隨意窩 Xuite日誌
http://blog.xuite.net/yctseng/notes/24568350-sed
bash - How do I use variables in a sed command? - Ask Ubuntu
https://askubuntu.com/questions/76808/how-do-i-use-variables-in-a-sed-command

其它相關文章推薦
Linux 常用指令教學懶人包
Linux cut 字串處理用法與範例
Linux find 尋找檔案/尋找資料夾用法與範例
Linux grep/ack/ag 搜尋字串用法與範例
Linux grep 搜尋字串用法與範例
Linux ag 搜尋字串用法與範例(比 grep 還快)
Linux tee 同時螢幕標準輸出和輸出到檔案用法與範例
Linux xargs 參數列表轉換用法與範例
Linux tail 持續監看檔案輸出用法與範例
Linux du 查詢硬碟剩餘空間/資料夾容量用法與範例
Linux wget 下載檔案用法與範例