sed替換命令
語法為:
sed ‘ [ address-range | pattern-range ] s/original-string/replacement-string/[substitute-flags] ’input-file
l address-range或pattern-range(即地址范圍和模式范圍)是可選的,如果沒有指定,那么sed將在所有行上進行替換
l s即執行替換命令substitute
l original-string是被sed搜索然后被替換的字符串,它可以是一個正則表達式
l replacement-sting替換后的字符串
l substitute-flags是可選的,下面會具體解釋
下面列舉一些示例
用Directory替換所有行中的Manager
[root@sishen ~]# sed 's/Manager/Director/' employee.txt
101,John Doe,CEO
102,Jason Smith,IT Director
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Director
只把包含Sales的行中的Manager替換為Director
[root@sishen ~]# sed '/Sales/s/Manager/Director/' employee.txt
101,John Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Director
全局標志 g
g代表全局(global)默認情況下,sed會替換每行中第一次出現的original-string,如果你要替換每行中出現的所有original-string,就需要用g
示例 用大寫A替換第一次出現的小寫字母a
[root@sishen ~]# sed 's/a/A/' employee.txt
101,John Doe,CEO
102,JAson Smith,IT Manager
103,RAj Reddy,Sysadmin
104,AnAnd Ram,Developer
105,JAne Miller,Sales Manager
把所有小寫字母a替換為大寫字母A
[root@sishen ~]# sed 's/a/A/g' employee.txt
101,John Doe,CEO
102,JAson Smith,IT MAnAger
103,RAj Reddy,SysAdmin
104,AnAnd RAm,Developer
105,JAne Miller,SAles ManAger
注意上述例子會在所有行上進行替換,因為沒有指定地址范圍
數字標志(1,2,3,·····)
使用數字可以指定original-string出現的次序,只有第n次出現的original-string才會觸發替換,每行數字從1開始,最大為512
比如/11會替換每行中第11次出現的original-string
把第二次出現的小寫字母a替換為大寫字母A
[root@sishen ~]# sed 's/a/A/2' employee.txt
101,John Doe,CEO
102,Jason Smith,IT MAnager
103,Raj Reddy,SysAdmin
104,Anand RAm,Developer
105,Jane Miller,SAles Manager
為了方便以下示例,首先建立如下文件
[root@sishen ~]# vim substitute-locate.txt
locate command is used to locate files
locate command uses datebases to locate files
locate command can also use regex for searching
~
把每行中第二次出的locate替換為find
[root@sishen ~]# sed 's/locate/find/2' substitute-locate.txt
locate command is used to find files
lcaote command uses datebases to locate files
locate command can also use regex for searching
打印標志p(print)
只打印替換后的行
[root@sishen ~]# sed -n 's/John/Johnny/p' employee.txt
101,Johnny Doe,CEO
在之前的數字標志的例子中使用/2來替換第二次出現的locate。第3行中locate只出現了一次所以沒有替換任何內容,使用p標志可以只打印替換過的兩行
[root@sishen ~]# sed -n 's/locate/find/2p' substitute-locate.txt
locate command is used to find files
locate command uses datebases to find files
[root@sishen ~]#
寫標志w
只把替換后的內容寫入到out6.txt文件中
[root@sishen ~]# sed -n 's/John/Johnny/w out6.txt' employee.txt
[root@sishen ~]# cat out6.txt
101,Johnny Doe,CEO
把每行中第二次出現的locate替換為find,把替換后的結果保存到文件中,同時顯示輸入文件所有內容
[root@sishen ~]# sed 's/locate/find/2w out7.txt' substitute-locate.txt
locate command is used to find files
locate command uses datebases to find files
locate command can also use regex for searching
[root@sishen ~]# cat out7.txt
locate command is used to find files
locate command uses datebases to find files
[root@sishen ~]# sed -n 's/locate/find/2w out7.txt' substitute-locate.txt
[root@sishen ~]# cat out7.txt
locate command is used to find files
locate command uses datebases to find files
[root@sishen ~]#
注意加上-n參數就不會輸出顯示在屏幕上
忽略大小寫標志i(ignore)
[root@sishen ~]# sed 's/john/Johnny/' employee.txt
101,John Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager
加上-i參數后才可以實現替換
[root@sishen ~]# sed 's/john/Johnny/i' employee.txt
101,Johnny Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager
執行命令標志w(excuate)
首先建立文件bash-file.txt
[root@sishen ~]# cat bash-file.txt
/etc/passwd
/etc/group
在bash-file.txt文件中的每行前面添加 ls -l 並打印結果
[root@sishen ~]# sed 's/^/ls -l/' bash-file.txt
ls -l/etc/passwd
ls -l/etc/group
在bash-file文件中的每行前面添加ls -l 並把結果作為命令執行
[root@sishen ~]# sed 's/^/ls -l /e' bash-file.txt
-rw-r--r-- 1 root root 1623 Oct 12 10:23 /etc/passwd
-rw-r--r-- 1 root root 818 Oct 12 10:23 /etc/group
使用替換標志組合
使用g,I,p和w的組合
下面的例子將把每行中出現的所有Manager或manager替換為Directory。然后把替換后的內容打印到屏幕上,同時把這些內容保存到out8.txt文件中
[root@sishen ~]# sed -n 's/manager/Director/igpw out8.txt' employee.txt
102,Jason Smith,IT Director
105,Jane Miller,Sales Director
sed替換命令分界符
首先新建一個文件path.txt
reading /usr/local/bin directory
限制使用sed把/usr/local/bin替換為/usr/bin,在下面的例子中,sed默認的分界符/都被\轉義
[root@sishen ~]# sed 's/\/usr\/local\/bin/\/usr\/bin/' path.txt
reading /usr/bin directory
這樣雖然實現了替換,但是操作中很繁瑣,所以你可以使用任何一個字符(包括字母,但是不建議這樣做)
作為sed替換命令的分界符。如 | 或 ^ 或!如
[root@sishen ~]# sed 'sA/usr/local/bin/A/usr/bin/A' path.txt
reading /usr/local/bin directory
[root@sishen ~]# sed 's|/usr/local/bin|/usr/bin|' path.txt
reading /usr/bin directory
[root@sishen ~]# sed 's@/usr/local/bin@/usr/bin/@' path.txt
reading /usr/bin/ directory
[root@sishen ~]# sed 's^/usr/local/bin^/usr/bin^' path.txt
reading /usr/bin directory
[root@sishen ~]# sed 's!/usr/local/bin!/usr/bin!' path.txt
reading /usr/bin directory
結果都一樣,看自己喜好了
單行內容以上執行多個命令
下面的例子演示了在模式空間內執行兩個替換命令的過程
[root@sishen ~]# sed '{
> s/Developer/IT Manager/
> s/Manager/Director/
> }' employee.txt #注意空格
101,John Doe,CEO
102,Jason Smith,IT Director
103,Raj Reddy,Sysadmin
104,Anand Ram,IT Director
105,Jane Miller,Sales Director
分析第4行執行過程
1. 讀取數據:在這一步,sed讀取內容到模式空間,此時模式空間的內容為:
104,Ananda Ram,Developer
2. 執行命令:第一個命令,s/Developer/IT Manager/執行后,模式空間的內容為:
104,Anand Ram,IT Manager
現在在模式空間上執行第二個命令s/Manager/Director/,執行后,模式空間內容為:
104,Ananda Ram,IT Director
謹記:sed在第一個命令執行的結果上,執行第二個命令
3. 打印內容:打印當前模式空間的內容,如下
104,Ananda Ram,IT Director
4. 重復循環:移動到輸入文件的下一行,然后重復執行第一步,即讀取數據
&的作用----獲取匹配到的模式
擋在replacement-string中使用&時,它會被替換成匹配到的original-string或正則表達式,這是個很有用的東西
給雇員ID(即第一列的3個數字)加上[ ],如101改成[101]
[root@sishen ~]# sed 's/^[0-9][0-9][0-9]/[&]/g' employee.txt
[101],John Doe,CEO
[102],Jason Smith,IT Manager
[103],Raj Reddy,Sysadmin
[104],Anand Ram,Developer
[105],Jane Miller,Sales Manager
把每一行放進<>中
[root@sishen ~]# sed 's/^.*/<&>/' employee.txt
<101,John Doe,CEO>
<102,Jason Smith,IT Manager>
<103,Raj Reddy,Sysadmin>
<104,Anand Ram,Developer>
<105,Jane Miller,Sales Manager>
分組替換(單個分組)
跟正則表達式中一樣,sed中也可以使用分組,分組以\(開始,以\)結束,分組可以用在回溯引用中,
回溯引用即重新使用分組所選擇的部分正則表達式,在sed替換命令的replacement-string中和正則表達式中,都可以使用回溯引用,
單個分組
[root@sishen ~]# sed 's/\([^,]*\).*/\1/g' employee.txt
101
102
103
104
105
上面例子中:
l 正則表達式\([^,0]*/)匹配字符串從開頭到一個逗號之間的所有字符(並將其放入第一個分組中)
l Replacement-string中的\1將代替匹配到的分組
l g 即是全局標志
下面例子只會顯示/etc/passwd的第一列,即用戶名
[root@sishen ~]# sed 's/\([^:]*\).*/\1/' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
uucp
operator
……
首先建立下面文件,以便使用
[root@sishen ~]# vim number.txt
1
12
123
1234
12345
123456
~
格式化輸出,增加可讀性
[root@sishen ~]# sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' number.txt
1
12
123
1,234
12,345
123,456
分組替換(多個分組)
可以使用多個\和(\)
划分多個分組,使用多個分組時,需要在replacement-string中使用\n來指定第n個分組,如下面的示例如只打印第一列(雇員ID)和第3列(雇員職位)
[root@sishen ~]# sed 's/^\([^,]*\),\([^,]*\),\([^,*]\)/\1,\3/' employee.txt
101,CEO
102,IT Manager
103,Sysadmin
104,Developer
105,Sales Manager
在這個例子中可以看到,original-string中,划分了3個分組,以逗號分隔
l ([^,]*\)第一個分組,匹配雇員ID
l ,為字段分隔符
l ([^,]*\)為第二個分組,匹配雇員姓名
l ,為字段分割符,上面的例子演示了如何使用分組
l \1代表第一個分組,(雇員ID)
l ,出現在第一個分組之后的逗號
l \3代表第二個分組(雇員職位)
注意:sed最多能處理9個分組,分別用\1至\9表示
交換第一列(雇員ID)和第二列(雇員姓名)
[root@sishen ~]# sed 's/^\([^,]*\),\([^,]*\),\([^,]*\)/\2,\1,\3/' employee.txt
John Doe,101,CEO
Jason Smith,102,IT Manager
Raj Reddy,103,Sysadmin
Anand Ram,104,Developer
Jane Miller,105,Sales Manager
sed專有的替換標志
\l 標志(小寫的 L,理解為lower)
當在replacement-string中使用\l標志時,它會把緊跟在其后的字符當作小寫字符來處理,如你所知,下面的例子將把John換成JOHNNY:
[root@sishen ~]# sed -n 's/John/JOHNNY/p' employee.txt
101,JOHNNY Doe,CEO
下面的例子將把JOHNNY 中的H換成h
[root@sishen ~]# sed -n 's/John/JO\lHNNY/p' employee.txt
101,JOhNNY Doe,CEO
\L 標志
當在replacement-string中使用\L標志時,它會把后面所有的字符都當小寫字符來處理,例如:
在replacement-string中的H前放置了\L 標志,它會把H和它后面的所有字符都換成小寫:
[root@sishen ~]# sed -n 's/John/JO\LHNNY/p' employee.txt
101,JOhnny Doe,CEO
\u標志(理解為upper)和\l類似,只不過是把字符換成大寫,當在replacemen-string中使用\u標志時,它會把緊跟其后的字符當作大寫字符來處理,下面的例子中,replacement-string里面的h前面有\u的標志,所以h將被換成大寫的H:
[root@sishen ~]# sed -n 's/John/jo\uhnny/p' employee.txt
101,joHnny Doe,CEO
\U標志
當在replacement-string中使用\U標志時,它會把后面所有的字符都當作大寫字符來處理。如下:replacement-string里面的h前面有U的標志,所以h及其后的所有字符都將被換成大寫:
[root@sishen ~]# sed -n 's/John/jo\Uhnny/p' employee.txt
101,joHNNY Doe,CEO
\E標志(理解為exit)
\E標志需要和\U或者\L一起使用,他將關閉\U或\L的功能,例如將字符串“Johnny Boy”的每個字符都以大寫的形式打印出來,因為在replacement-string前面使用了\U標志
[root@sishen ~]# sed -n 's/John/\UJohnny Boy/p' employee.txt
101,JOHNNY BOY Doe,CEO
下面將把John換成JOHNNY Boy
[root@sishen ~]# sed -n 's/John/\UJohnny\E Boy/p' employee.txt
101,JOHNNY Boy Doe,CEO
因為在Johnny后面使用了\E標志,關閉了\U的功能
替換標志的用法
如下將雇員ID都顯示為大寫,職位都顯示為小寫:
[root@sishen ~]# sed 's/\([^,]*\),\([^,]*\),\([^,]*\)/\U\2\E,\1,\L\3/' employee.txt
JOHN DOE,101,ceo
JASON SMITH,102,it manager
RAJ REDDY,103,sysadmin
ANAND RAM,104,developer
JANE MILLER,105,sales manager
這個例子中
l \U\2\3把第二個分組轉換為大寫,然后使用\E關閉轉換
l \L\3 把第三分組轉換為小寫
