模式空間與保持空間
sed在正常情況下將處理的行讀入模式空間(pattern space),腳本
的"sed command"就是一條接著一條進行處理绒疗,直到腳本執(zhí)行完畢,然后該行被輸出,模式被清空到腥,接著重復執(zhí)行剛才的動作账锹,文件中新的一行被讀入萌业,直到文件處理完畢。
工作模式:模式空間和保持空間介紹
模式空間:初始化為空奸柬,處理完一行后會自動輸出到屏幕并清除模式空間生年。
保持空間:初始化為一個空行,也就是默認帶一個\n廓奕,處理完后不會自動清除抱婉。
模式空間:可以想成工程里面的流水線,數(shù)據(jù)之間在它上面進行處理桌粉,用于處理文本行蒸绩。
保持空間:可以想象成倉庫,我們在進行數(shù)據(jù)處理的時候铃肯,
作為數(shù)據(jù)的暫存區(qū)域患亿,用于保留文本行,是保存已經處理過的
輸入行押逼,默認有一個空行步藕。
#sed -e ‘s/pig/cow/’ -e ‘s/cow/horse/’
#sed '1{p;p}' a.txt
11111111
11111111
11111111
22222222
33333333
44444444
55555555
66666666
置換:模式空間和保持空間(暫存空間)
h 把模式空間內容覆蓋到保持空間中
H 把模式空間內容追加到保持空間中
g 把保持空間內容覆蓋到模式空間中
G 把保持空間內容追加到模式空間中
x 交換模式空間與保持空間的內容
[root@localhost ~]# sed 'G' test.txt
1111111
222222222
33333333
444444444
5555555555
666666666
777777777
[root@localhost ~]# cat test.txt
1111111
222222222
33333333
444444444
5555555555
666666666
777777777
》》將1,2,3(2,3是追加進去的)行模式空間的放到保持空間惦界,在將保持空間里的三行追加到第四行的模式空間里
[root@localhost ~]# sed '{1h;2,3H;4G}' test.txt
1111111
222222222
33333333
444444444
1111111
222222222
33333333
5555555555
666666666
777777777
[root@localhost ~]# sed '{1h;2x;3g;$G}' test.txt
1111111
1111111
222222222
444444444
5555555555
666666666
777777777
222222222
反轉:
/1/{
h
d
}
/2/{
G
}
控制流
! 命令取反 例: 1!d 刪除第一行以外的行
{} 命令組合 命令用分號分隔 {1h;G} 可以理解為 -e 參數(shù)的另一種寫法
= 打印行號(輸入行的號碼,而非處理的次數(shù)行號) 例如: sed -n '2{=;p}' infile
n 讀入下一行到模式空間 例:'4{n;d}' 刪除第5行
N 而是追加下一行到模式空間,再把當前行和下一行同時應用后面的命令
P 輸出多行模式空間的第一部分咙冗,直到第一個嵌入的換行符為止表锻。在執(zhí)行完腳本的最后一個命令之后,模式空間的內容自動輸出乞娄。
P命令經常出現(xiàn)在N命令之后和D命令之前瞬逊。
D 刪除模式空間中直到第一個換行符的內容。它不會導致讀入新的輸入行仪或,相反确镊,它返回到腳本的頂端,將這些指令應用與模式空間剩余的內容范删。
這三個命令能建立一個輸入蕾域、輸出循環(huán),用來維護兩行模式空間到旦,但是一次只輸出一行旨巷。
這個循環(huán)的目的是只輸出模式空間的第一行,然后返回到腳本的頂端將所有的命令應用于模式空間的第二行添忘。沒有這個循環(huán)采呐,當執(zhí)行腳本中的最后一個命令時,模式空間中的這兩行都將被輸出搁骑。
刪除文件倒數(shù)第二行
sed 'N;$!P;D' a.txt
刪除文件最后兩行
sed 'N;$!P;$!D;$d' a.txt
#練習:
```
將第一行插入到每個偶數(shù)行的后面
$ sed '1h;0~2G' a.txt
11111111
22222222
11111111
33333333
44444444
11111111
55555555
66666666
11111111
顛倒輸出
$ sed '1!G;h;$!d' rev.txt
xyz
def
abc
$
大寫轉換
樣本文件 a.txt
find the Match statement
Consult the Get statement.
using the Read statement to retrieve data
將 the 和statement之間的單詞轉換成大寫
腳本:changsrc
# capitalize statement names
/the .* statement/{
h
s/.*the \(.*\) statement.*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/\(.*\)\n\(.*the \).*\( statement.*\)/\2\1\3/
}
腳本方法
-f 參數(shù) 引用腳本(腳本的末尾不能有空格制表符或其他文本)
# 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
跳轉的位置與標簽相關聯(lián)
如果有標簽則跳轉到標簽所在的后面行繼續(xù)執(zhí)行
如果沒有標簽則跳轉到腳本的結尾處.
標簽 以冒號開始后接標簽名 不要在標簽名前后使用空格
跳轉到標簽指定位置
[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)循環(huán)執(zhí)行,直到條件不滿足
:top; 定義一個top標簽
s/seker/blues/; cmd1
/seker/b top; 如果模式匹配則跳轉到top標簽
s/5/555/ 當上一條模式不匹配時,既會繼續(xù)執(zhí)行這一條
選擇執(zhí)行
[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 ~]#
命令分析: 執(zhí)行cmd1,再去模式匹配,成功則跳轉到cmd3開始執(zhí)行,否則(模式不匹配)會按命令順序逐個執(zhí)行
s/seker/blues/; cmd1
/seker/b end;
s/5/555/; cmd2
:end;
s/5/666/ cmd3
另一種選擇執(zhí)行
[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 ~]#
命令分析: 執(zhí)行cmd1;模式匹配cmd2成功則執(zhí)行cmd3;否則執(zhí)行cmd2,再跳轉到腳本末尾
s/seker/blues/; cmd1
/seker/b end;
s/5/555/; cmd2
b;
:end;
s/5/666/ cmd3
測試命令,如果前一個替換命令執(zhí)行成功則跳轉到腳本末尾 (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 ~]
與標簽關聯(lián),跳轉到標簽位置
[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