Skip to main content

sed

教學網站

分隔符號

除了常見的 / ,也能使用 @ , | , %

Tip: 有時遇到要搜尋某些特殊符號,可能會需要更換不同的分隔符號。

For s command

# 將 /usr/bin 加上 local 成為 /usr/bin/local
sed 's@/usr/bin@&/local@g' path.txt

Other command

# 開頭要加一個反斜線
echo $PATH | sed -n '\@/usr/local/sbin@p'
常用語法範例
# 移除註解, 空白行
sed '/^#\|^$\| *#/d' my.conf
# 只移除註解文字,但不刪除整行
sed 's/#.*//' file.txt

# 搜尋取代: 每一行第 1 個 Linux 換成 Unix
sed 's/Linux/Unix/' linuxteck.txt
# 搜尋取代: 每一行第 1 個 Linux 換成 Unix (不分大小寫)
sed 's/Linux/Unix/i' linuxteck.txt

# 搜尋取代: 每一行第 2 個 Linux 換成 Unix
sed 's/Linux/Unix/2' linuxteck.txt
# 搜尋取代: 第二行第 1 個 Linux 換成 Unix
sed '2 s/Linux/Unix/' linuxteck.txt
# 搜尋取代: 全文的 Linux 換成 Unix
sed 's/Linux/Unix/g' linuxteck.txt

# 列印: 行號
sed -n p linuxteck.txt
# 列印: 第 2-4 行
sed -n '2,4p' linuxteck.txt
# 列印: 移除第 2-4 行
sed '2,4d' linuxteck.txt
# 列印: 第 2-3, 5-6 行
sed -n -e '2,3p' -e '5,6p' linuxteck.txt
# 列印: 包含 operating 的行
sed -n /operating/p linuxteck.txt

# 每一行之間加一個空白行
sed G linuxteck.txt
# 在每個註解行下方加一個空行
sed '/^#/G' file.txt
列出搜尋內容
# 列出第 100 行以下的所有文字
# 若要刪除,可將 p 換成 d。
sed -n '100,$p'  my.txt

# 列出第 3 行以上的所有文字
sed '3q' my.txt

# 列出第 130 行
sed -n '130{p;q}' my.txt

# 列出第 100 - 130 行文字
sed -n '100,130p' my.txt
sed -n '100,130p;130q' my.txt

# 列出關鍵字 all 以下所有行
sed -n '/all/,$p' my.txt

# 列出關鍵字 start 以上的所有文字
sed '/start/q' file.txt

# 搜尋關鍵字,並列出這個段落的所有文字
sed -n '/keyword/,/^$/p'

# 列出關鍵字 Top 與 Bottom 之間的所有文字
sed -n '/Top/,/Bottom/p'

# 搜尋字串的那一行
sed -n "/PATTERN/p" my.txt
sed -n "/PATN1\|PATN2\|PATN3/p" my.txt
刪除搜尋內容
# 刪除行首為# 的行
sed '/^#/d' 

# 刪除行首為 # 或空白的行
sed '/^#\|^$/d'
sed '/^#/d;/^$/d' # for AIX

# 刪除多個關鍵字的行, ADMIN_ERP_ROLE, RPT01,...
sed '/ADMIN_ERP_ROLE/d;/RPT01/d'

# 刪除空白行
sed '/^$/d'
sed '/^\s*$/d'

# 刪除第 42 行文字
sed 42d my.txt

# 刪除空格
sed 's/[[:space:]]//g' mywords
sed 's/^[ \t]*//;s/[ \t]*$//' mywords
sed 's/^\s*\|\s*$//g' mywords

# 刪除所有行尾的空格字元
sed 's/[[:space:]]*$//'

# 刪除行尾的 ^M (CR 字元)
sed 's/^M//g'      NOTE: to get ^M type CTRL+V followed by CTRL+M
sed 's/\r$//g'

# 刪除 iXXXX 的帳號, XXXX 是數字
sed '/^i[0-9]*/d' mypasswd

# 刪除最後一行
sed '$d' my.txt
搜尋後取代/插入文字
# 在第 2 行的上方,插入文字 xxx
sed '2i xxx' my.txt

# 在第 2 行的下方,插入文字 yyy
sed '2a yyy' my.txt

# 在第二行的行尾,插入文字 ****
sed '3 s/$/ ****/'

# 在搜尋的行下方新增字串
sed -e '/patterm/ a\newstring' my.txt

# 在所有文字的行首加上 #
sed 's/^/# /' my.txt

# 在所有文字的行尾加上 End
sed 's/$/ End/' my.txt

# 將每一行裡是兩個以上空白字元, 都換成一個 comma 符號
sed "s/  \+/,/g"

# 快速取代字串
sed 's/old/new/' mywords
sed 's|old|new|' mywords

# 搜尋關鍵字 'astlogdir =>' 的這一行,取代行字串為 'astlogdir => /mnt/usb/asterisk_log'
# .*$ 表示行尾前的所有字串
sed -i 's/astlogdir =>.*$/astlogdir => \/mnt\/usb\/asterisk_log/g'

# 搜尋 'none',並且在該行行首加上 '#'
sed 's/none/#&/g' mywords 

# 在字串  'daemon' 的下方插入另一個檔案 3.txt 的內容
sed '/daemon/r 3.txt' mywords 
sed '/INCLUDE/r foo.h' sample.c

# 搜尋文字 'daemon',將符合的內容寫到檔案 3.txt
sed -n '/daemon/w 3.txt' 1.txt 

# 將符合文字 'root' 內容的下一行,插入特定的文字 'test test'
[root@linux-3 ~]# sed ‘/root/a test test’ 1.txt
root:x:0:0:root:/root:/bin/bash
test test
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 

# 將符合文字 'daemon' 內容的上一行,插入特定的文字 'test test'
[root@linux-3 ~]# sed '/^daemon/i test test' 1.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
test test
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

# 搜尋所有文字是 'ext3' 的,用 [ ] 框起來
sed 's/ext3\+/[&]/g' my.txt

# 搜尋文字並取代部份的內容
sed -i 's/^\(User\|Group\).*/\1 asterisk/' /etc/httpd/conf/httpd.conf

# 搜尋開頭是 revoke 的每一行尾,加上分號. & 表示符合搜尋的內容
sed 's/^revoke.*$/&\;/' revoke_winieop.sql

# 搜尋每一行, 並格式為 <<<STRING>>>. "^.*$" 表示每一行, & 表示符合搜尋的內容
sed 's@^.*$@<<<&>>>@g' path.txt

# 將 /usr/bin 加上 local 成為 /usr/bin/local
sed 's@/usr/bin@&/local@g' path.txt

備份 *.sh 檔案且移除第一行 #!/bin/bash

sed -i.bak '1i #!/bin/bash' edit.sh

執行多個規則

sed -e '/^#/d' -e '/^$/d' 

找出關鍵字的右側字串內容

$ cat cookie.txt
xxxx  FALSE   /       FALSE   0       PHPSESSID       dbbr5nsmib9tgm0h97sbq8ovd0

$ cat cookie.txt | sed 's/^.*PHPSESSID[ \t]*//' 
dbbr5nsmib9tgm0h97sbq8ovd0

找出行的左側內容
列出 10.14.25.196 與 GA016E38 (Hex IP)

$ cat input.txt
 
 GA160223.MAE3.219594040120
10.14.25.196.49611.200203080358
GA016E38.O5FA.259D81215343
10.4.1.29.41266.200114031620
GA12640A.M6EE.20EDC3093010

$ sed 's/^\(.*\)\.[A-Z0-9]*\.[A-Z0-9]*/\1/' input.txt

GA160223
10.14.25.196
GA016E38
10.4.1.29
GA12640A

對 CSV 檔案的內容,將所有分隔符號 comma 置換成 @@,但必須排除有包含 comma 的文字敘述,這些文字內的 comma 前個字元會有個空白

sed 's/\(,\)\([^ ]\)/@@\2/g' orig.csv

s 搜尋

\( \) \( \) 用括弧區分兩個字元

[^ ] 非空白的字元

\2 第二個字元,這裡要配合括弧的用法

g 作全文置換,若沒有此參數,預設只會置換第一個符合的字元

搜尋 A.AA B.BB C.CC 3個數值,並以指定的格式輸出

sed 's/^\([0-9]\+\.[0-9]\+\) \([0-9]\+\.[0-9]\+\) \([0-9]\+\.[0-9]\+\).*$/1-minute: \1\n5-minute: \2\n15-minute: \3/g' /proc/loadavg

^\([0-9]\+\.[0-9]\+\) \([0-9]\+\.[0-9]\+\) \([0-9]\+\.[0-9]\+\).*$ 搜尋語法

1-minute: \1\n5-minute: \2\n15-minute: \3 輸出語法

搜尋/驗證 IP 位址

sed -n '/\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}/p' my.txt

取代所有的 mailbox = xxx 為 mailbox = xxx@context

sed 's/^mailbox = [0-9]*/&@context/g' users.conf

搜尋特定區段的 AllowOverride None

只取代這個區段所包含的關鍵字
<Directory "/var/www/html">
...
<Directory>

sed -i ':a;N;$!ba;s/AllowOverride None/AllowOverride All/2' /etc/httpd/conf/httpd.conf

擷取 { } 所包含的所有文字

<br/> <b>Notice</b>: Undefined variable: sn in <b>/var/www/raida/service/fix.php</b> on line <b>259</b><br/> {"server":"RAIDA17","sn":"","status":"success","message":"Fixed: Unit's AN was changed to the PAN. Update your AN to the new PAN.","time":"2017-04-08 06:08:25"}

echo $( cat http_get.txt ) | sed  's/.* \({.*}\)$/\1/'

擷取 [ ] 內的文字

echo "[1070059:1,1070060:1,1070039:1]" | sed  's/^\[\(.*\)\]$/\1/'
排除法搜尋
# 移除所有行尾結束字元不是雙引號的
sed '/\"$/!d'

# 移除所有行開頭不是 "2021-09-26-23.13.02.097806" 這樣格式的內容
sed '/^\"[0-9]\+\-[0-9]\+\-[0-9]\+\-[0-9]\+\.*/!d'

# 排除 PATTERN1 + 搜尋 PATTERN2 + 取代 WORDS
sed '/PATTERN1/!s/PATTERN2/WORDS/g'

# 除第5行以外的所有文字,搜尋 foo 並以 bar 取代
sed '5!/s/foo/bar/' file.txt

# 排除 start 到 end 之間段落的所有文字
sed -rn '/start/,/end/ !p' file.txt
段落搜尋
# 列出關鍵字 Top 與 Bottom 之間段落的所有文字
sed -n '/Top/,/Bottom/p'

# 在 start 與 end 之間段落,搜尋井字開頭的文字,並刪除;井字前的文字仍會保留
sed -E '/start/,/end/ s/#.*//' file.txt
進階應用範例

將數字 123456 格式化成 123,456

echo "123456" | sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g'

(W)elcome (T)o (T)he (G)eek (S)tuff

echo "Welcome To The Geek Stuff" | sed 's/\(\b[A-Z]\)/\(\1\)/g'

Get the list of usernames in /etc/passwd

sed 's/\([^:]*\).*/\1/' /etc/passwd

變數資料

sed -n '\@/usr/local/bin@p' <<< $PATH
Markdown 內容

設定 "第 X 章" 為標題 Level 5 格式

# Search: **第 一 章 總則**
# Replace: ##### 第 一 章 總則

sed 's/^.*\(第\ .*\ 章 .*\)\*\*.*$/##### \1/' markdown/勞動基準法.md

# Serch: **法規名稱:**性別平等工作法
# Replace: #### 法規名稱:性別平等工作法

sed -i 's/^\*\*\(法規名稱:\)\*\*\(.*\)$/#### \1\2/' markdown/勞動基準法.md

設定 "第 X 條" 為標題 Level 6 格式

# Search: **第 1 條**
# Replace: ###### 第 1 條

sed 's/^.*\(第\ .*\ 條\).*$/###### \1/' markdown/勞動基準法.md

修正不正確的斷行

1
要派單位不得於派遣事業單位與派遣勞工簽訂勞動契約前,有面試該派遣勞工或其他指定特定派遣勞工之行為。

2
要派單位違反前項規定,且已受領派遣勞工勞務者,派遣勞工得於要派單位提供勞務之日起九十日內,以書面向要派單位提出訂定勞動契約之意思表示。

修正後

1 要派單位不得於派遣事業單位與派遣勞工簽訂勞動契約前,有面試該派遣勞工或其他指定特定派遣勞工之行為。

2 要派單位違反前項規定,且已受領派遣勞工勞務者,派遣勞工得於要派單位提供勞務之日起九十日內,以書面向要派單位提出訂定勞動契約之意思表示。
sed 'N;s/^\([123456789]\)\n/\1 /' markdown/勞動基準法.md