sed:Stream Editor文本流編輯,sed是一個“非交互式的”面向字符流的編輯器。在使用sed處理時,它把當前處理的行存儲在臨時緩沖區中,稱為“模式空間”(pattern space),接看用sed命令處理緩沖區中的內容,處理完成后,把緩沖區的內容送往屏幕顯示,接着處理下一行,不斷重復直到文件末。默認情況下不會改變文件內容,除非使用了寫入的命令,將內容更新。它的特點如下:
- 1.它可以同時處理多個文件多行的內容(使用-e或者{})
- 2.可以不對原文件改動,把整個文件輸入到屏幕(不使用-i)
- 3.可以把只匹配到模式的內容輸入到屏幕上(使用-n)
- 4.對原文件改動,但是不會再屏幕上返回結果(使用-i)
sed命令的語法格式:
- sed的命令格式: sed [option] '[匹配模式] sed的內部命令' filename
- sed的腳本格式:sed [option] -f 'sed script' filename
options:是可選的選擇或參數
匹配模式:是可選的用於在文件中每一行進行匹配到模式,模式可以是正則,也可以是文件的行號
內部的命令:是可選的,但是兩個單引號是必須的
sed命令的選項(option):
- -n :只打印模式匹配的行
- -e :直接在命令行模式上進行sed動作編輯,此為默認選項。。。使用多個-e可以進行多項編輯
- -f :后跟腳本,是將sed的動作寫在一個文件內,用–f filename 執行filename內的sed動作
- -i :直接修改源文件內容,使用-i后不會再在終端輸出文件內容
- -r :支持擴展表達式
- --follow-symlinks:
- -l N, --line-length=N
- --posix: disable all GNU extensions.
- -s: consider files as separate rather than as a single continuous long stream.
- -u,: load minimal amounts of data from the input files and flush the output buffers more often
- -z, --null-data separate lines by NUL characters
sed的動作(sed command):
p: 打印匹配行,因為sed默認打印文件中所有的行,所以使用p后匹配行會被打印兩次;p可以跟-n配合使用,用於只打印匹配行
-
- sed -n '2p' learn_sed.txt 打印第二行
- sed -n '/^first/!p' learn_sed.txt 打印非first開頭的行,注意!的位置
a:在定位行號后插入新文本信息 i: 在定位行號前插入新文本信息
-
- sed '/first/i nihao' learn_sed.txt或sed '/first/inihao' learn_sed.txt 在匹配到first的行前新增一行nihao,i選項后的空格會被忽略
- sed '/first/i nihao\n 22' learn_sed.txt 添加多行時,多行間使用\n來換行,\n后的空格是被識別的
- sed '1i testdata' myfile 在文件的行首添加一行
- sed '$a testdata' myfile 在文件的行尾追加一行,使用-a時,在匹配行后添加一行,a/i后的空格會被忽略
d:刪除定位行,sed的刪除操作是針對文件的行,如果想刪除行中的某個字符,那就用替換
-
- sed '/^#/d' myfile 刪除以#開頭的行
- sed '/^#/!d' myfile 刪除非#開頭的行,即顯示以#開頭的行
- sed '1d' myfile 刪除第一行
- sed '$d' myfile 刪除最后一行
- sed '2,4d' myfile 刪除指定的2~4行
- sed '/\<line\>/d' learn_sed.txt #\<\>是單詞界定符,刪除行中有line單詞的行。。如果某一行為firstline,由於字符串中的line不是個單詞,所以該行不會刪除
s:使用替換模式替換相應模式,s后緊跟的符號為地址定界符,一般由3個組成,定界符可以是/$#@等特殊字符
-
- sed '/second/s/^/my /' learn_sed.txt #在匹配行的行首添加my。(先匹配后替換)
- sed '/first/s/$/ END/' learn_sed.txt #在匹配行的行尾添加 END。(先匹配后替換)
- sed 's/second/my &/' learn_sed.txt #在匹配字符串的前邊添加my ,其中&代表替換字符串即second。
- sed 's/second/& my/' learn_sed.txt #在匹配字符串的后邊添加 my。
- sed '/first/s/\(.*\)/\1 END/' learn_sed.txt #使用正則方式在first所在行的行尾添加 END,其中\(\)表示分組,.*表示任意字符,\1引用第一個分組,在此處引用的是前邊匹配的整行,然后在行尾添加 END。
- sed -r 's/[0-9][0-9]$/&.5/' datafile //&代表在查找串中匹配到的內容
- sed -r 's/(Mar)got/\1ianne/g' datafile
- sed 's/^/start /' learn_sed.txt 在每行行首添加start
- sed 's/$/ end/' learn_sed.txt 在每行行尾添加end
- sed '1,3s/^/#/' learn_sed.txt 在1到3行的行首添加#
- sed -i '/second/s/22\.1/10.12/' myfile #匹配second的行,把22.1替換成10.12由於.號有特殊意義所有需要轉義
- sed -i '/second/s/#//' myfile #匹配second的行,把#替換成空,即去掉#號,也一般用作去掉#注釋
- sed -i 's/root/(&)/g' myfile #把root用括號括起來,&表示引用前面匹配的字符
w filename:寫文本到一個文件,類似輸出重定向 >,把正在用sed操作的文件內容寫到另外一個文件中
-
- sed 's/first/new first/w new.txt' learn_sed.txt #w表示保存,new.txt文件名
- 執行該命令會將匹配行數據寫入到新文件new.txt中
r filename:從另一個文件中讀文本,類似輸入重定向 <,讀取一個文件到正在用sed操作的文件中
從new2.txt中讀取數據放在new.txt中的匹配行后 | |||
---|---|---|---|
cat new.txt
cat new2.txt
|
sed '/new1/r new2.txt' new.txt
|
sed '/new/r new2.txt' new.txt
|
sed '1r new2.txt' new.txt
|
q:結束或退出
sed
-
- sed '5q' /etc/passwd#打印前5行
{}:使用{}實現多項編輯,不同編輯命令之間用分號
- sed -n '1,2{p;=}' learn_sed.txt/sed -n '1,2{=;p}' learn_sed.txt #兩個編輯命令相互約束生效,行號只打印到了2
- sed -n '1,3!{=;p}' learn_sed.txt #使用!對前邊的匹配模式取反,注意!的位置
- sed -n '/^first/!{/^$/!p}' learn_sed.txt #打印非first開頭以及非空的行,先過濾出非first開頭的行,然后在此基礎上過濾出空行
- sed '/root/{s/bash/nologin/;s/0/1/g}' test #匹配root的行,把bash替換成nologin,且把0替換成1
n:從另一個文件中讀文本下一行,並從下一條命令而不是第一條命令開始對其的處理
-
- sed '/test/{ n; s/aa/bb/; }' example 如果test被匹配,則移動到匹配行的下一行,替換這一行的aa,變為bb,並打印該行,然后繼續。
N:在數據流中添加下一行以創建用於處理的多行組
g:全局替換,當某行中有多個匹配項時,
-
- 使用g可以全局匹配
- 不使用g只匹配第一個
- 使用2g會匹配第二個及第二個之后的匹配項
- 使用2只匹配第二個
-
- echo 'first line line line'|sed '/line/s/line/line22/' 輸出為first line22 line line,只匹配了第一個
- echo 'first line line line'|sed '/line/s/line/line22/g' 輸出為first line22 line22 line22,全局匹配
- echo 'first line line line'|sed '/line/s/line/line22/2g' 輸出為first line line22 line22,匹配了第二個及以后的匹配項
- echo 'first line line line'|sed '/line/s/line/line22/2' 輸出為first line line22 line,只匹配了第二個
y:傳送字符,替換單個字符,將字符替換為另一字符(不能對正則表達式使用y命令)
test_sed中的內容為:
-
- 1234567890
- 2345678901
執行sed 'y/1234567890/ABCDEFGHIJ/' test_sed的輸出為:
-
- ABCDEFGHIJ
- BCDEFGHIJA
sed '1,10y/abcde/ABCDE/' example把1–10行內所有abcde轉變為大寫,注意,正則表達式元字符不能使用這個命令。
!:反向選擇
-
- sed -r '3!d' /etc/hosts
- sed -n '/^first/!p' learn_sed.txt 打印非first開頭的行,注意!的位置
文件內容 | 模式 | 舉栗 |
---|---|---|
cat learn_sed.txt first line second line three line last line |
x x為行號 |
sed '2p' learn_sed.txt (打印 文件中的第二行,因為sed默認打印文件中所有的行,所以第二行會打印兩次) sed -n '2p' learn_sed.txt (使用-n可以只打印匹配到的行) |
x,y 表示行號從x到y |
sed -n '1,3p' learn_sed.txt |
|
|
/pattern 查詢包含模式的行 |
sed -n '/first/p' learn_sed.txt (打印文件中能夠匹配first字符的行) |
/pattern/,/pattern 查詢兩個模式之間的行 |
sed -n '/first/,/three/p' learn_sed.txt(打印從包含first的行開始到包含three的行)
sed '/first/,/second/d' learn_sed.txt(刪除從包含first的行到包含second的行) sed '/second/,/first/d' learn_sed.txt(刪除從包含second的行到包含first的行,由於first在second之后,所以會刪除second之后的行) |
|
/pattern/,x 打印匹配pattern的行到x行之間的行,若包含pattern在x行之后,則只打印匹配pattern的行 |
sed -n '/second/,3p' learn_sed.txt(打印文件中從匹配second的行到第3行)
sed -n '/second/,1p' learn_sed.txt(若包含second的行在第1行之后,則只打印匹配到second的行)
|
|
x,/pattern/ 打印x行到匹配pattern的行之間的行,若x行在包含pattern的行之后,則只打印x行到文件最后一行的數據
|
sed -n '1,/second/p' learn_sed.txt(打印文件中從1行到匹配到second的行)
sed -n '3,/second/p' learn_sed.txt(第3行在匹配到second的行之后,所以只打印了第3行之后的數據)
|
|
x,y! 查詢不包含指定行號x和y的行 |
sed -n '1,3!p' learn_sed.txt(打印不包含第一行到第三行數據的行) sed -n '1!p' learn_sed.txt(打印不包含第一行數據的行) |
|
sed命令中引用變量
1.sed命令里面沒有默認的變量時可以把單引號改成雙引號
- var=first
- echo 'first line'|sed "s/$var/test/" #輸出為test line
- echo 'first line'|sed 's/$var/test/' #輸出為first line ${var}沒有被識別
2.sed命令里面有默認的變量時,sed里面的語句必須用單引
- sed "$a test" learn_sed.txt #會報錯sed: can't find label for jump to `est'
- sed '$a test' learn_sed.txt #在文件行尾新增一行test
3.sed命令里面有默認的變量時,sed里面的語句必須用單引,自己定義的變量需要加單引號。
- sed '$a '$var'' learn_sed.txt #正確使用
- sed '$a $var' learn_sed.txt #自定義變量沒有被識別,必須使用單引號將變量括起來才行
sed 中的多項編輯
1.使用多個-e對單個文件進行多項操作,多項編輯命令分別生效,多項命令的執行順序對結果有影響。如果兩個命令都是替換命令,那么第一個替換命令將影響第二個替換命令的結果。
- sed -e '/^first/d' -e '/^$/d' learn_sed.txt 先刪除以first開頭的行,再刪除空行
- sed -e '/second/d' -e '/first/d' learn_sed.txt或者使用sed -r '/first|second/d' learn_sed.txt 刪除包含second或first的行
- sed -n -e '1,3p' -e '=' learn_sed.txt或者sed -n -e '=' -e '1,3p' learn_sed.txt 兩個命令分別生效,打印行號時顯示了4
2.使用{}實現多項編輯,不同編輯命令之間用分號
- sed -n '/^first/!{/^$/!p}' learn_sed.txt #打印非first開頭以及非空的行
- sed '{/first/d;/second/d}' learn_sed.txt 刪除包含second或first的行
- sed -n '1,2{p;=}' learn_sed.txt/sed -n '1,2{=;p}' learn_sed.txt #兩個編輯命令相互約束生效,行號只打印到了2
- sed -n '1,3!{=;p}' learn_sed.txt #使用!對前邊的匹配模式取反,注意!的位置
3.多項編輯直接用分號分割
- sed -r '1,3d; s/Hemenway/Jones/' datafile
- sed -r '2s/WE/1000phone/g; 2s/Gray/YYY/g' datafile 等同於sed -r '2{s/WE/1000phone/g; s/Gray/YYY/g}'
datafile
2)使用正則表達式、擴展正則表達式(必須結合-r選項)
^ |
匹配行首符合條件的內容,用法格式"^pattern" |
|
$ |
匹配行尾符合條件的內容,用法格式"pattern$" |
|
^$ |
空白行 |
|
. |
匹配任意單個字符 |
|
* |
匹配緊挨在前面的字符任意次(0,1,多次) |
|
.* |
匹配任意長度的任意字符 |
|
\? |
匹配緊挨在前面的字符0次或1次 |
|
\{m,n\} |
匹配其前面的字符至少m次,至多n次 |
|
\{m,\} |
匹配其前面的字符至少m次 |
|
\{m\} |
精確匹配前面的m次\{0,n\}:0到n次 |
|
\< |
錨點詞首----相當於 \b,用法格式:\<pattern |
|
\> |
錨點詞尾,用法格式:\>pattern |
|
\<pattern\> |
單詞錨點 |
|
分組,用法格式:pattern,引用\1,\2 |
||
[] |
匹配指定范圍內的任意單個字符 |
|
[^] |
匹配指定范圍外的任意單個字符 |
|
[:digit:] |
所有數字, 相當於0-9, [0-9]---> [[:digit:]] |
|
[:lower:] |
所有的小寫字母 |
|
[:upper:] |
所有的大寫字母 |
|
[:alpha:] |
所有的字母 |
|
[:alnum:] |
相當於0-9a-zA-Z |
|
[:space:] |
空白字符 |
|
[:punct:] |
所有標點符號 |
[ ] 需要匹配的時候,需要轉義(這個是叛徒)
|
echo "[ ]"|sed 's/\[.*\]/aaa/g'
|
( ) 需要匹配的時候,不要轉義
|
$echo "( )"|sed 's/( )/c/g'
|
{ } 需要匹配的時候,不要轉義
|
$echo "{ }"|sed 's/{ }/c/g'
|
使用{ }作為特殊字符時候,需要轉義
|
$echo "333"|sed 's/[0-9]\{3\}/ccc/g'
|
當需要適配符,需要使用\1來替換正則表達式的對應參數時:
不能寫(regrexxxx)
要寫\(regrexxxx\)
|
$echo "{1234567}"|sed 's/{\([0-9]*\)}/\1/g'
|
+ *
在做為特別字符時候+必須轉義為\+
而*則不需要
|
echo "ccc"| sed 's/c*/aaa/g'#正確
echo "ccc"| sed 's/c\*/aaa/g'#錯誤
echo "ccc"| sed 's/c+/aaa/g'#錯誤
echo "ccc"| sed 's/c\+/aaa/g'#正確
|
sed的經典例子及常用操作
1.cat file.txt的輸出如下,期望處理以下文件內容,將域名取出並進行計數排序
內容如下:
- http://www.baidu.com/index.<a target="_blank" href="http://www.2cto.com/kf/qianduan/css/" class="keylink" style="border:none; padding:0px; margin:0px; color:rgb(51,51,51); text-decoration:none; font-size:14px">html</a>
- http://www.baidu.com/1.html
- http://post.baidu.com/index.html
- http://mp3.baidu.com/index.html
- http://www.baidu.com/3.html
- http://post.baidu.com/2.html
期望結果如下,輸出內容為域名的出現的次數 域名:
實現方式:
- cat file.txt | sed -e ' s/http:\/\///' -e ' s/\/.*//' | sort | uniq -c | sort -rn
- awk -F/ '{print $3}' file.txt |sort -r|uniq -c|awk '{print $1"\t",$2}'
2.用grep結合sed取出網卡的ip地址
ifconfig | grep -B1 "inet addr" |grep -v "\-\-" |sed -n -e 'N;s/eth[0−9].*\n.*addr:[0−9]{1,3}\.[0−9]{1,3}\.[0−9]{1,3}\.[0−9]{1,3}.*/\1 \2/p'
3.批量替換多個文件中的字符串
sed -i "s/原字符串/新字符串/g" `grep 原字符串 -rl 所在目錄`
其中,-i 表示inplace edit,就地修改文件,-r 表示搜索子目錄,-l 表示輸出匹配的文件名,這個命令組合很強大,要注意備份文件。
4.替換命令中的注意點
- $ sed 's/test/mytest/g' example 在整行范圍內把test替換為mytest。如果沒有g標記,則只有每行第一個匹配的test被替換成mytest。
- $ sed -n 's/^test/mytest/p' example (-n)選項和p標志一起使用表示只打印那些發生替換的行。也就是說,如果某一行開頭的test被替換成mytest,就打印它。
- $ sed 's/^192.168.0.1/&localhost/'example &符號表示替換換字符串中被找到的部份。所有以192.168.0.1開頭的行都會被替換成它自已加localhost,變成192.168.0.1localhost。
- $ sed -n 's/\(love\)able/\1rs/p' example love被標記為1,所有loveable會被替換成lovers,而且替換的行會被打印出來。
- $ sed 's#10#100#g' example 不論什么字符,緊跟着s命令的都被認為是新的分隔符,所以,“#”在這里是分隔符,代替了默認的“/”分隔符。表示把所有10替換成100。
5.使用|同時匹配兩種模式
- sed -r '/first|second/d' learn_sed.txt或者sed -nr '/first|second/p' learn_sed.txt
- sed -nr '/^(patt1|patt2)$/p' 匹配整條行
- sed -n '/^\(patt1\|patt2\)$/p' 也可以刪除-r並添加轉義符
6.刪除/替換 所有匹配結果中的第一個
- sed -i '0,/happy/{/happy/d}' test.txt #刪除從0行到happy行里面的happy行,相當於刪除第一個happy行
- sed -i '0,/happy/{/happy/s/$/aa/}' test.txt #先匹配從0行到happy行,然后找到有happy的行進行替換
- echo 'a c b d'|sed 's/[ ]\+/ /g'
- echo 'a c b d'|sed -e 's/[[:space:]][[:space:]]*/ /g'
- echo 'a c b d'|sed -i 's/[ ][ ]*/ /g'
Only in h264_fpga/h264_random/case_2711: stream_0.yuv_0 Only in h264_fpga/h264_random/case_6093: stream_0.yuv_276248 Files h264_cmodel/h264_random/case_6342/stream_0.yuv and h264_fpga/h264_random/case_6342/stream_0.yuv differ Only in h264_fpga/h264_random/case_6342: stream_0.yuv_0 Only in h264_fpga/h264_random/case_6342: stream_0.yuv_450 Only in h264_fpga/h264_random/case_6342: stream_0.yuv_475 Files h264_cmodel/h264_random/case_6443/stream_0.yuv and h264_fpga/h264_random/case_6443/stream_0.yuv differ Only in h264_cmodel/h264_random/case_7120: stream_0.yuv Only in h264_cmodel/h264_random/case_7156: stream_0.yuv
- cat log_${1}_bak|sed 's/.*case_//g'|sed 's/[^0-9].*stream_0.yuv.*$/ /g'|sort|uniq|tr "\n" " ">log_${1}
- cat log_${1}_bak|awk -F"case_" '{print $2}'|awk -F"[:/]" '{print $1}'|sort|uniq|tr "\n" " ">log_${1}
- cat log_${1}_bak|sed 's#.*case_\([0-9].*\)[:/].*$#\1#g'|sort|uniq|tr "\n" " ">log_${1} #使用\1來替換正則表達式的對應參數
- 通過 :a創建一個標記
- 通過N追加當前行和下一行到模式區域
- 如果處於最后一行前,跳轉到之前的標記處。 $!ba ($! 意思是不在最后一行做這操作 (最后一行就被當成最后的一行).
- 最后置換操作把模式區域(就是整個文件)的每一個換行符換成一個空格。
擴展知識:
- Ubuntu:sed -i '2d' test.txt
- Mac:sed -i '' '3d' test.txt Mac中必須使用'',否則報錯sed: 1: "test.txt": undefined laebl 'est.txt',原因是mac強制要求備份,使用''可以只保留一份
- 使用&表示替換字符串 sed 's/a/&i/' aaa.txt ,將每行第一個被匹配到的a都被替換為ai
- 緊挨着s命令的符號被認為是分割符 sed 's#a#i#' aaa.txt 分割符為#
參考: