linux 之sed用法


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

  • new1
  • new2

cat new2.txt 

  • 222
  • 333

sed '/new1/r new2.txt' new.txt

  • new1
  • 222
  • 333
  • new2

sed '/new/r new2.txt' new.txt 

  • new1
  • 222
  • 333
  • new2
  • 222
  • 333

sed '1r new2.txt' new.txt

  • new1
  • 222
  • 333
  • new2

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行)

  • second line
  • three line

sed -n '/second/,1p' learn_sed.txt(若包含second的行在第1行之后,則只打印匹配到second的行)

  • second line
 

x,/pattern/ 打印x行到匹配pattern的行之間的行,x行在包含pattern的行之后,則只打印x行到文件最后一行的數據

 

sed -n '1,/second/p' learn_sed.txt(打印文件中從1行到匹配到second的行)

  • first line
  • second line

sed -n '3,/second/p' learn_sed.txt(第3行在匹配到second的行之后,所以只打印了第3行之后的數據)

  • three line
  • last line
 

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"

  • #######sed的匹配模式支持正則表達式#####################  
  • sed -n '/r*t/p' /etc/passwd#打印匹配r有0個或者多個,后接一個t字符的行  
  • sed -n  '/.r.*/p' /etc/passwd#打印匹配有r的行並且r后面跟任意字符  
  • sed -n '/o*/p' /etc/passwd#打印o字符重復任意次  
  • sed -n '/o\{1,\}/p' /etc/passwd#打印o字重復出現一次以上  
  • sed -n '/o\{1,3\}/p' /etc/passwd#打印o字重復出現一次到三次之間以上  

$

匹配行尾符合條件的內容,用法格式"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:]

所有標點符號

 
sed正則表達式匹配,各種括號的轉義和不轉義
[ ] 需要匹配的時候,需要轉義(這個是叛徒)
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的輸出如下,期望處理以下文件內容,將域名取出並進行計數排序 

內容如下:

期望結果如下,輸出內容為域名的出現的次數 域名:  

實現方式:

  • 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[09].*\n.*addr:[09]{1,3}\.[09]{1,3}\.[09]{1,3}\.[09]{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的行進行替換
7.sed替換多個空格
  1. echo 'a c b d'|sed 's/[ ]\+/ /g'
  2. echo 'a c b d'|sed -e 's/[[:space:]][[:space:]]*/ /g'
  3. echo 'a c b d'|sed -i 's/[ ][ ]*/ /g'
1)[:space] 即為空格
2)*號代表0個或多個,+代表一個或多個
 
8.獲取文件中case id
文件log_${1}_bak為:
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來替換正則表達式的對應參數
9.sed/tr替換換行符為空格
1 sed 命令 sed命令的輸出結尾有換行符
sed ':a;N;$!ba;s/\n/ /g' 這將在一個循環里讀取整個文件,然后將換行符替換成一個空格。
說明:
  • 通過 :a創建一個標記
  • 通過N追加當前行和下一行到模式區域
  • 如果處於最后一行前,跳轉到之前的標記處。 $!ba ($! 意思是不在最后一行做這操作 (最后一行就被當成最后的一行).
  • 最后置換操作把模式區域(就是整個文件)的每一個換行符換成一個空格。
示例追加:
$ echo -e "1\n2" | sed ':a;N;$!ba;s/\n/ /g' 輸出為:1 2
sed ':label;N;s/\n/ /;b label' 更深處的參考: https://my.oschina.net/shelllife/blog/118337
 
2 tr命令 tr命令的輸出結尾沒有換行符
cat country.txt | tr "\n" " "

擴展知識:

  • 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 分割符為#

參考:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM