本篇 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. 希望將裡面的在 settings.conf 裡取代所有的 Alan
字串, 替換成 Barry
,sed 指令如下,g
表示全部取代,沒有 g
的話只會取代一次,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 $ sed -i 's/oldtext/newtext/g' <filename> $ sed -i 's/oldtext/newtext/g' *.txt $ sed -i 's/abc\ d/a\ bcd/g' <filename> $ sed -i 's/^http/https/g' <filename> $ sed -i 's/com.*/edu/g' <filename> $ 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 find ./ -iname "*.txt" -type f | xargs sed -i 's/http/https/g' 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 grep -ri "http" * -l | xargs sed -i 's/http/https/g' grep -ri "http" * -l | xargs sed -i "" 's/http/https/g'
如果 grep 換成 ag 的話,1 2 3 4 ag "http" -l | xargs sed -i 's/http/https/g' 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'
結果為
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 Ubuntuhttps://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 下載檔案用法與範例