sed用法總結

Aminiy發表於2013-12-02
1.sed


[root@stu93 sed]# sed -r '/\n!G;s/(.)(.*\n)/&\2\1;//D;s/.//' abc.txt 
回去查
流編輯器 stream editer,是以行為單位的處理程式


sed 流編輯器 stream editer


語法
   sed [options] 'command' in_file[s]
options 部分
-n 阻止輸入行自動輸出
-e
-i
-f 指令碼檔案
-r 支援擴充正則
command 部分
'[地址1,地址2] [函式] [引數(標記)]'

定址的方法 1.數字 2.正則
數字
  十進位制數
1 單行   
1,3 範圍 從第一行到第三行
2,+4 匹配行後若干行
4,~3   從第四行到下一個3的倍數行
2~3 第二行起每間隔三行的行
$ 尾行
1! 除了第一行以外的行
2.sed  -n '' /etc/passwd 阻止輸入行自動顯示
3.sed -n  'p' /etc/passwd
4.'cmd'
定址 函式[標記];函式
5. [root@stu93 ~]# sed  -n '1{p;p}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
[root@stu93 ~]# sed  -n '1p;3p' /etc/passwd
[root@stu93 ~]# sed -n '/^id/s/[0-6]/3/p' /etc/inittab 
id:3:initdefault:
6 [root@stu93 ~]# cat -n /etc/passwd | sed '6,~3p'倍數行
[root@stu93 ~]# cat -n /etc/passwd | sed '6,+3p'重複行
[root@stu93 ~]# cat -n /etc/passwd | sed '6~3p'間隔行
[root@stu93 ~]# cat -n /etc/passwd | sed '6p'指定行
[root@stu93 ~]# cat -n /etc/passwd | sed '6!p'除了6行
[root@stu93 ~]# cat -n /etc/passwd | sed '$p'最後一行
[root@stu93 ~]# sed -n '/root\|seker/p' /etc/passwd  含root和seker的行
[root@stu93 ~]# sed -n '/^root/,/^adm/p' /etc/passwd 以root和adm開頭的行
[root@stu93 sed]# sed  '2c xyz.txt' abc.txt
aaaaaaaaaaa
xyz.txt
ccccccccccc


7. 基本正則
正則介紹


 ^ 行首
 $ 行尾
 . 除了換行符以外的任意單個字元
 * 前導字元的零個或多個
 .* 所有字元貪婪性取多不取少
 [] 字元組內的任一字元
 [^] 對字元組內的每個字元取反(不匹配字元組內的每個字元)
 ^[^] 非字元組內的字元開頭的行
 [a-z] 小寫字母
 [A-Z] 大寫字母
 [a-Z] 小寫和大寫字母
四則運算 [+ - * /]不可以 [- + * /]減號方前面就可以了
 [0-9] 數字
 \< 單詞頭 單詞一般以空格或特殊字元做分隔,連續的字串被當做單詞
 \> 單詞尾

. 匹配除換行符職位的任意單個字元,awk中可以匹配換行符
* 匹配任意一個(包括零個)在它前面的字元
[...] 匹配方括號中的任意一個字元,^為否定匹配, -表示字元的範圍
^ 作為正規表示式的第一個字元,匹配行的開始。在awk中可以嵌入換行符
$ 作為正規表示式的最後一個字元,匹配行的結尾。在awk中可以嵌入換行符
\{n,m\} 匹配出現的n到m次數, \{n\}匹配出現n次。\{n,\}匹配至少出現n次
\ 轉義字元
\< \>單詞
sed '/正則/'
8. 擴充套件正則
sed -r '擴充正則'
grep -E
egrep
grep \
+ 匹配前面的正規表示式的一次出現或多次出現
? 匹配前面的正規表示式的零次出現或一次出現
| 可以匹配前面的或後面的正規表示式(替代方案)
() 對正規表示式分組
{n,m} 匹配出現的n到m次數, {n}匹配出現n次。{n,}匹配至少出現n次,大多數awk都不支援,用於POSIX egrep和POSIX awk

[root@stu93 ~]# cat 4
egg
cow
[root@stu93 ~]# sed -e 's/egg/cow/' -e 's/cow/pig/ ' 4
pig
pig

[root@stu93 ~]# sed -e 's/cow/pig/' -e 's/egg/cow/'  4
cow
pig
此時應該考慮順序問題 可以變換下替換順序
擴充套件正則 加 -r 引數 或轉義
 sed -n '/roo\?/p' /etc/passwd  
 sed -rn '/roo?/p' /etc/passwd
 ? 前導字元零個或一個
 + 前導字元一個或多個
 abc|def abc或def
 a(bc|de)f abcf 或 adef
 x\{m\}   x出現m次
 x\{m,\}  x出現m次至多次(至少m次)

 x\{m,n\} x出現m次至n次


函式
增刪改
 a\ 後插
 c\ 替換
 i \前插
 d 刪除
這些命令每一個都要求後面加一個反斜槓用於轉義第一個行尾
輸入輸出
 p 列印匹配的行 一般和 -n 引數連用,以遮蔽預設輸出
 r 從檔案中讀入
 w 寫入到檔案中
y 字元替換(變形)
q 退出
控制流
 !  命令取反 例: 1!d 刪除第一行以外的行
 {} 命令組合 命令用分號分隔 {1h;G} 可以理解為 -e 引數的另一種寫法


 =  列印行號(輸入行的號碼,而非處理的次數行號) 例如: sed -n '2{=;p}' infile
 n  讀入下一行到模式空間 例:'4{n;d}' 刪除第5行
 N  是追加下一行到模式空間,再把當前行和下一行同時應用後面的命令
 R 兩個檔案個行輸出
 r 輸出一行之後另個檔案全不輸出之後再輸出前一個檔案的另一行
 c
 i 對記憶體操作
P 輸出當前模式空間中匹配的第一部分(第一個字元到第一個換行符為止)
D 從第一個字元刪除到第一個換行符結束 它不會匯入新的輸入行 而是返回輸入行頂部繼續執行
[root@stu93 ~]# sed -n 's/root/ABCDEF/gp' /etc/passwd

ABCDEF:x:0:0:ABCDEF:/ABCDEF:/bin/bash
operator:x:11:0:operator:/ABCDEF:/sbin/nologin


[root@stu93 ~]# sed -n 's/root/ABCDEF/2p' /etc/passwd
root:x:0:0:ABCDEF:/root:/bin/bash
[root@stu93 ~]# sed -n 's/root/ABCDEF/3p' /etc/passwd
root:x:0:0:root:/ABCDEF:/bin/bash
[root@stu93 ~]# sed -n 's/root/ABCDEF/gp' /etc/passwd
ABCDEF:x:0:0:ABCDEF:/ABCDEF:/bin/bash
operator:x:11:0:operator:/ABCDEF:/sbin/nologin

[root@stu93 ~]#cat a.txt
123
123
123  
[root@stu93 ~]#sed -r '$!N; /^(.*)\n\1$/!P;D' a.txt
123
高階命令
NDP sed -r '$!N;/^(.*)\n\1$/!p;D'
[root@stu93 ~]# cat a
this is the unix
system and unix is like the
unix system
[root@stu93 ~]# sed 'N;s/\n/''/;s/ system/ opting system/;P;D' a
this is the unix opting system and unix is like the
unix opting system

替換
 s 字串替換 s/old/new/

$ sed -n 's/root/ABCDEF/p' /etc/passwd

ABCDEF:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/ABCDEF:/sbin/nologin

定址
[root@stu93 ~]# cat a.txt 
beijing ,chain
shanghai ,chain
aaa
tianjin .chain
bbb
chengdu .chain


[root@stu93 ~]# sed '/^aaa/,/^bbb/{s/tianjin/TJ/;s/chain/CN/}' a.txt 
beijing ,chain
shanghai ,chain
aaa
TJ .CN
bbb
chengdu .chain


[root@stu93 sed]# sed -n '1,3s/root/AA/gp' passwd
AA:x:0:0:AA:/AA:/bin/bash
[root@stu93 ~]# sed '=' /etc/passwd | sed 'N;s/\n/ /' 每兩行處理為一行

三行處理成一行
[root@stu93 ~]# cat b.txt 
2010-09-23
192.168.0.1
shutdown
2010-09-22
192.168.0.2
reboot
2010-09-24
192.168.0.3
init 0
[root@stu93 ~]#  sed 'N;N; s/\n/ /g' b.txt
2010-09-23 192.168.0.1 shutdown
2010-09-22 192.168.0.2 reboot
2010-09-24 192.168.0.3 init 0

連著的多個空行變為一個空行輸出
[root@stu93 ~]# cat c.txt 
1111111


3333




666666666

100000000
[root@stu93 ~]# sed '/^$/{N; /^\n$/D }' c.txt  D 刪除第一個空行
[root@stu93 ~]# sed '/^$/d;$!G' c.txt      $!G表示最後一行不執行G規則
1111111


3333


666666666


100000000
[root@stu93 ~]# time sed '2q' a.txt   q 對大檔案操作較快
[root@stu93 ~]# time sed -n '1,2p' a.txt 對小檔案可以
\(\) 儲存被匹配的字元 以備反向引用\N時使用 最多9個標籤 標籤順序從左至右
& 替換時使用,在不定義標籤時使用(反向引用)

試做:
   
刪除第一個單詞


刪除最後一個單詞


將第一個單詞和最後一個單詞兌換位置



y 字元替換(變形)


工作模式 模式空間和保持空間介紹



[root@stu93 ~]# sed  '1{p;p}' a.txt
11111111
11111111
11111111
22222222
33333333
44444444
55555555
66666666
置換 模式空間和保持空間(暫存空間)
 h 把模式空間內容覆蓋到保持空間中
 H 把模式空間內容追加到保持空間中
 g 把保持空間內容覆蓋到模式空間中
 G 把保持空間內容追加到模式空間中
 x 交換模式空間與保持空間的內容


[root@stu93 ~]# cat test.sh 
1111111
2222222
3333333
4444444
[root@stu93 ~]# sed  '{1h;2,3H;4G}'  ./test.sh 
1111111
2222222
3333333
4444444
1111111
2222222
3333333
[root@stu93 ~]# sed  '{1h;2x;3g;$G}'  ./test.sh 
1111111
1111111
2222222
4444444
2222222

[root@stu93 sed]# sed '1H;2,3{G};$g' xyz.txt 
1111111
2222222


1111111
3333333


1111111


1111111


[root@stu93 sed]# sed '1h;2,3H;$!G' xyz.txt 
1111111
1111111

2222222
1111111
2222222

3333333
1111111
2222222
3333333
                                                                                                                                                                                                                                                                                                                                                                                                     
4444444
cmd qianhou
sed null\n
1h 11111111
$!G 1111  11111111
==>1111  1111
2H 22221111 2222
$!G 2222 1111 2222       11112222
==>2222 1111 2222
3H 33331111 2222 3333
$!G 3333 1111 2222 3333
==>3333 1111 2222 3333
$!G 4444

[root@stu93 sed]# tac xyz.txt 
4444444
3333333
2222222
1111111
[root@stu93 sed]# sed '4G;2,3{G;h;d};1{h;d};' xyz.txt 
[root@stu93 sed]# sed '4G;3{G;h;d};2{G;h;d};1{h;d};' xyz.txt 
4444444
3333333
2222222
1111111
4G 44444/n/n
=>4444/n
3{G;h;d} 3333 /n
3333 3333
3333
==>3333
2{G;h;d} 2222
2222 2222
2222
==>2222
1{h;d} 1111 1111
1111
==>1111
[root@stu93 sed]# sed  '1!G;h;$!d' xyz.txt

試做題
奇數行和偶數行互換
[root@stu93 ~]# cat 3 .txt
1
2
11
22
111
222
[root@stu93 ~]# sed -e '/1/{h;d}' -e '/2/{G}' 3.txt
每行的後面加空行
[root@stu93 ~]# sed 'G' 3.txt
每行的後面加2個空行
[root@stu93 ~]# sed 'G;G' 3txt
顯示檔案的前10行
[root@stu93 ~]# sed -n '1,10p' /etc/passwd




每行的前面加空行
[root@stu93 ~]# sed  -e 'x;P;x'  3.txt


將第一行插入到每個偶數行的後面


$ sed  '1h;0~2G' a.txt


11111111


22222222


11111111


33333333


44444444


11111111


55555555


66666666


11111111


$


顛倒輸出


[root@stu93 ~]#  sed '1!G;h;$!d' rev.txt
[root@stu93 ~]# sed -n '1!G;h;$p' 3


xyz


def


abc

指令碼方法
四 編寫sed指令碼


模式空間
sed   -e  ‘s/pig/cow/’ -e ‘s/cow/horse/’
sed   -e ‘s/cow/horse/’ -e ‘s/pig/cow/’
 
定址上的全域性透視
全域性操作   範例file2.txt
$ sed '/Beijing/s/CN/China/g' file2.txt


刪除所有的行
d
刪除檔案的最後兩行
[root@stu93 ~]# sed 'N;$!P;$!D;$d' c.txt 
只刪除第一行
1d


使用定址符號$,刪除最後一行
$d


刪除空行,正規表示式必須封閉在斜槓//當中
/^$/d


刪除.TS和.TE標記的tbl輸入
/^\.TS/,/^\.TE/d


刪除第五行到結尾所有的行
5,$d

混合使用行地址和模式地址
$ sed '1,/^$/d' file2.txt


刪除除了那些行以外的行
1,5!d
分組命令
/^\.TS/,/^\.TE/{
      /^$/d
}


/^\.TS/,/^\.TE/{
/^$/d
  s/^\.ps 10/.ps 8/
  s/^\.vs 12/.vs 10/
}

     -f 引數 引用指令碼(指令碼的末尾不能有空格製表符或其他文字)
# cat sed.sh 
2,4d
s/777/seker/
s/999/seker&seker/
# sed -f sed.sh test.txt 
1111111
5555555
6666666
seker7777
8888888
seker999seker9999
#


  在指令碼中指明直譯器為sed
# cat sed.sh 
#!/bin/sed -f
2,4d
s/777/seker/
s/999/seker&seker/
# ./sed.sh test.txt 
1111111
5555555
6666666
seker7777
8888888
seker999seker9999



高階流控命令 b分支 t測試
分支命令用於無條件轉移,測試命令用於有條件轉移


分支 branch
   跳轉的位置與標籤相關聯
如果有標籤則跳轉到標籤所在的後面行繼續執行
如果沒有標籤則跳轉到指令碼的結尾處.
   標籤 以冒號開始後接標籤名 不要在標籤名前後使用空格
跳轉到標籤指定位置
:top
  cmd1
  cmd2
/aa/b top
cmd3




cmd1
/aa/b end
cmd2
:end
cmd3


cmd1
/aa/b dothree
cmd2
b
:dothree
cmd3

[root@stu254 ~]# grep seker /etc/passwd
seker:x:500:500::/home/seker:/bin/bash
[root@stu254 ~]#
[root@stu254 ~]# grep seker /etc/passwd |sed ':top;s/seker/blues/;/seker/b top;s/5/555/' 
blues:x:55500:500::/home/blues:/bin/bash
[root@stu254 ~]# 


命令分析:讓單次替換(cmd1)迴圈執行,直到條件不滿足
:top; 定義一個top標籤
s/seker/blues/; cmd1
/seker/b top; 如果模式匹配則跳轉到top標籤
s/5/555/ 當上一條模式不匹配時,既會繼續執行這一條


選擇執行
[root@stu254 ~]#  grep 'seker' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;:end;s/5/666/'
blues:x:66600:500::/home/seker:/bin/bash
[root@stu254 ~]# 


zorro:x:501:501::/home/zorro:/bin/bash
[root@stu254 ~]#  grep 'zorro' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;:end;s/5/666/'
zorro:x:6665501:501::/home/zorro:/bin/bash
[root@stu254 ~]# 


命令分析: 執行cmd1,再去模式匹配,成功則跳轉到cmd3開始執行,否則(模式不匹配)會按命令順序逐個執行
s/seker/blues/; cmd1
/seker/b end;
s/5/555/; cmd2
:end;
s/5/666/ cmd3


另一種選擇執行
[root@stu254 ~]#  grep 'seker' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;b;:end;s/5/666/'
blues:x:66600:500::/home/seker:/bin/bash


[root@stu254 ~]#  grep 'zorro' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;b;:end;s/5/666/'
zorro:x:55501:501::/home/zorro:/bin/bash
[root@stu254 ~]# 


命令分析: 執行cmd1;模式匹配cmd2成功則執行cmd3;否則執行cmd2,再跳轉到指令碼末尾 
s/seker/blues/; cmd1
/seker/b end;
s/5/555/;  cmd2
b;
:end;
s/5/666/ cmd3




測試命令,如果前一個替換命令執行成功則跳轉到指令碼末尾 (case結構)
[root@stu254 ~]#  grep 'seker' /etc/passwd |sed 's/seker/ABC/;t;s/home/DEF/;t;s/bash/XYZ/'
ABC:x:500:500::/home/seker:/bin/bash


[root@stu254 ~]#  grep 'zorro' /etc/passwd |sed 's/seker/ABC/;t;s/home/DEF/;t;s/bash/XYZ/'
zorro:x:501:501::/DEF/zorro:/bin/bash
[root@stu254 ~]#


與標籤關聯,跳轉到標籤位置
[root@stu254 ~]#  grep 'seker' /etc/passwd |sed 's/seker/ABC/;t end;s/home/DEF/;t;:end;s/bash/XYZ/'
ABC:x:500:500::/home/seker:/bin/XYZ
[root@stu254 ~]#
  
[seker@seker ~]$ grep 'zorro' /etc/passwd |sed 's/seker/ABC/;t end;s/home/DEF/;t;:end;s/bash/XYZ/'
zorro:x:501:501::/DEF/zorro:/bin/bash


[seker@seker ~]$


runsed 對輸入檔案作永久性改變
#!/bin/bash
        for x
do
        echo "editing $x: \c"
        if test "$x" = sedscr;then


        echo "not editing sedscript"
        elif test -s $x;then
        sed -f sedscr $x > /tmp/$x$$
        if test -s /tmp/$x$$
        then
                if cmp -s /tmp/$x$$
                then
                        echo "file not changed: \c"
                else
                        mv $x.bak # save original, just in case
                        cp /tmp/$x$$ $x
                fi
                echo "done"
                else
                echo "Sed produced an empty file\c"
                echo "- check your sedscript."
        fi
        rm -f /tmp/$x$$
        else
                echo "original file is empty."
        fi
        done
        echo "all done"

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24492954/viewspace-1061863/,如需轉載,請註明出處,否則將追究法律責任。