與vim不同,sed是一種非交互式的文本編輯器,同時(shí)它又是面向字符流的,每行數(shù)據(jù)經(jīng)過sed處理后輸出。
sed?[OPTION]...?[script]?[file]...?sed的工作過程是這樣的:首先,初始化兩個(gè)數(shù)據(jù)緩沖區(qū)模式空間和保持空間;sed讀取一行輸入(來自標(biāo)準(zhǔn)輸入或文件),去掉結(jié)尾的換行符(\n)后置于模式空間中,然后針對(duì)模式空間中的字符串開始執(zhí)行‘sed命令’,每個(gè)命令都可以有地址與之相關(guān)聯(lián),地址可以看成是條件,只有在條件成立時(shí),相關(guān)的命令才被執(zhí)行;所有可執(zhí)行命令都處理完畢后,仍處于模式空間中的字符串會(huì)被追加一個(gè)換行符后打印輸出;之后讀取下一行輸入做同樣的處理,直到主動(dòng)退出(q)或輸入結(jié)束。
地址
地址可以是如下的形式
1、number 表示行號(hào)
2、first~step 表示從first(數(shù)字)行開始,每隔step(數(shù)字)行
3、$ 表示最后一行(注意當(dāng)出現(xiàn)在正則表達(dá)式中時(shí)表示行尾)
4、/regexp/ 表示匹配正則表達(dá)式regexp(關(guān)于正則表達(dá)式,請(qǐng)參見這一篇)
5、\%regexp% 表示匹配正則表達(dá)式regexp,%可以換成任意其他單個(gè)字符。(用于regexp包含斜線/的情況)
6、/regexp/I 匹配正則表達(dá)式regexp時(shí)不區(qū)分大小寫
7、/regexp/M 啟用正則多行模式,使$不止匹配行尾,還匹配n或r之前的位置;使^不止匹配行首,還匹配n或r之后的位置。此時(shí)可以用(\`)匹配模式空間的開頭位置,用(\')匹配模式空間的結(jié)束位置。
還可以用逗號(hào),分隔兩個(gè)地址來表示一個(gè)范圍
表示從匹配第一個(gè)地址開始,直到匹配第二個(gè)地址或文件結(jié)尾為止。如果第二個(gè)地址是個(gè)正則表達(dá)式,則不會(huì)對(duì)第一個(gè)地址匹配行進(jìn)行第二個(gè)地址的匹配;如果第二個(gè)地址是行號(hào),但小于或等于第一個(gè)地址匹配行行號(hào),則只會(huì)匹配一行(第一個(gè)地址匹配行)。
8、0,/regexp/ 這種情況下,正則表達(dá)式regexp會(huì)在第一行就開始進(jìn)行匹配。只有第二個(gè)地址是正則表達(dá)式時(shí),第一個(gè)地址才能用0。
9、addr1,+n表示匹配地址addr1和其后的n行。
10、addr1,~n表示從匹配地址addr1開始,直到n的倍數(shù)行為止。
如果沒有給出地址,所有的行都會(huì)匹配;在地址或地址范圍后追加字符!表示對(duì)地址取反,所有不匹配的行才會(huì)被處理。
選項(xiàng)
-n 默認(rèn)時(shí)每一行處理過的字符串都會(huì)被打印輸出,此選項(xiàng)表示關(guān)閉此默認(rèn)行為。只有被命令p作用的字符串才會(huì)被輸出。
-f file表示從file中讀取sed命令
-i 表示原地修改。應(yīng)用此選項(xiàng)時(shí),sed會(huì)創(chuàng)建一個(gè)臨時(shí)文件,并將處理結(jié)果輸出到此文件,處理完畢后,會(huì)將此臨時(shí)文件覆蓋至原文件。
-r 表示使用擴(kuò)展的正則表達(dá)式
命令
p表示打印模式空間內(nèi)容,通常配合選項(xiàng)-n一起使用
[root@centos7?~]#?seq?5?1?2?3?4?5?[root@centos7?~]#?只輸出第二行到第四行?[root@centos7?~]#?seq?5|sed?-n?'2,4p'?2?3?4? [root@centos7?~]#???d 刪除模式空間內(nèi)容,立即處理下一行輸入。
#刪除最后一行?[root@centos7?~]#?seq?5|sed?'$d'?1?2?3?4? [root@centos7?~]#??q 立即退出,不再處理任何命令和輸入(只接受單個(gè)地址)
[root@centos7?~]#?seq?5|sed?'/3/q'?1?2?3? [root@centos7?~]#??n 如果沒有使用選項(xiàng)-n,輸出模式空間中內(nèi)容后,讀取下一行輸入并覆蓋當(dāng)前模式空間內(nèi)容。如果沒有更多的輸入行,sed會(huì)退出執(zhí)行。
[root@centos7?~]#?seq?9|sed?-n?'n;p'?2?4?6?8? [root@centos7?~]#?注意多個(gè)命令用分號(hào)分隔??s/regexp/replacement/flag 表示用replacement替換模式空間中匹配正則表達(dá)式regexp的部分。在這里符號(hào)/可以換成任意單個(gè)字符。
[root@centos7?~]#?echo?"hello123world"|sed?'s/[0-9]\+/,/'???hello,world? #注意這里+需要轉(zhuǎn)義,如果使用選項(xiàng)-r則無需轉(zhuǎn)義??在replacement中
1、\n (n為1-9中的一個(gè)數(shù)字)表示對(duì)正則表達(dá)式中分組(...)的引用;
[root@centos7?~]#?echo?"hello123world"|sed?-r?'s/[a-z]+([0-9]+)[a-z]+/\1/'?123?[root@centos7?~]#?echo?"hello123world"|sed?-r?'s/([a-z]+)[0-9]+([a-z]+)/\1,\2/'? hello,world??2、&表示模式空間中所有匹配regexp的部分;
[root@centos7?~]#?echo?"hello123world"|sed?-r?'s/[0-9]+/:&:/'? hello:123:world??3、\L 將后面的字符轉(zhuǎn)化成小寫直到 \U 或 \E 出現(xiàn);
4、\l 將下一個(gè)字符轉(zhuǎn)化為小寫;
5、\U 將后面的字符轉(zhuǎn)化成大寫直到 \L 或 \E 出現(xiàn);
6、\u 將下一個(gè)字符轉(zhuǎn)化為大寫;
7、\E 停止由 \L 或 \U 起始的大小寫轉(zhuǎn)化;
[root@centos7?~]#?echo?"hello123world"|sed?-r?'s/^([a-z]+)[0-9]+([a-z]+)$/\U\1\E,\u\2/'?HELLO,World? [root@centos7?~]#???flag
1、n數(shù)字n表示替換第n個(gè)匹配項(xiàng)
[root@centos7?~]#?head?-1?/etc/passwd?root:x:0:0:root:/root:/bin/bash?#替換冒號(hào)分隔的第五部分為空?[root@centos7?~]#?head?-1?/etc/passwd|sed?'s/[^:]\+://5'? root:x:0:0:/root:/bin/bash??2、g表示全局替換
[root@centos7?~]#?echo?"hello123world"|sed?'s/./\U&\E/'?Hello123world?[root@centos7?~]#??[root@centos7?~]#?echo?"hello123world"|sed?'s/./\U&\E/g'?HELLO123WORLD?[root@centos7?~]#?#當(dāng)數(shù)字n和g同時(shí)使用時(shí),表示從第n個(gè)匹配項(xiàng)開始替換一直到最后匹配項(xiàng)?[root@centos7?~]#?head?-1?/etc/passwd|sed?'s/[^:]\+://4g'? root:x:0:/bin/bash/??3、p表示如果替換成功,則打印模式空間內(nèi)容。
4、w file表示如果替換成功,則輸出模式空間內(nèi)容至文件file中。
5、I和i表示匹配regexp時(shí)不區(qū)分大小寫。
[root@centos7?~]#?echo?'HELLO123world'|sed?-r?'s/[a-z]+//Ig'?123? [root@centos7?~]#??6、M和m表示啟用正則多行模式(如前所述)。(講命令N時(shí)再舉例)
[root@centos7?~]#?echo?hello|sed?'y/el/LE/'???????hLEEo? [root@centos7?~]#??a text表示輸出模式空間內(nèi)容后追加輸出text內(nèi)容
[root@centos7?~]#?seq?3|sed?'1,2a?hello'??1?hello?2?hello?3? [root@centos7?~]#??i text表示輸出模式空間內(nèi)容之前,先輸出text內(nèi)容
[root@centos7?~]#?seq?3|sed?'$ihello'?1?2?hello?3? [root@centos7?~]#???c text表示刪除匹配地址或地址范圍的模式空間內(nèi)容,輸出text內(nèi)容。如果是單地址,則每個(gè)匹配行都輸出,如果是地址范圍,則只輸出一次。
[root@centos7?~]#?seq?5|sed?'1,3chello'?hello?4?5?[root@centos7?~]#?seq?5|sed?'/^[^3-4]/c?hello'??hello?hello?3?4? hello??=表示打印當(dāng)前輸入行行號(hào)
[root@centos7?~]#?seq?100|sed?-n?'$='?100?[root@centos7?~]#?seq?100|sed?-n?'/^10\|^20/='?10?20?100? [root@centos7?~]#?轉(zhuǎn)義的|表示邏輯或??r file表示讀取file的內(nèi)容,并在當(dāng)前模式空間內(nèi)容輸出之后輸出
[root@centos7?~]#?cat?file??hello?world?[root@centos7?~]#?seq?3|sed?'1,2r?file'?1?hello?world?2?hello?world?3? [root@centos7?~]#???w file表示輸出模式空間內(nèi)容至file中
N讀入一行內(nèi)容至模式空間后,再追加下一行內(nèi)容至模式空間(此時(shí)模式空間中內(nèi)容形如 line1\nline2 ),如果不存在下一行,sed會(huì)退出。
[root@centos7?~]#?seq?10|sed?-n?'N;s/\n/?/p'?1?2?3?4?5?6?7?8?9?10?[root@centos7?~]#?#s命令的m?flag舉例?[root@centos7?~]#?seq?3|sed?'N;s/^2/xxx/'??1?2?3?[root@centos7?~]#?seq?3|sed?'N;s/^2/xxx/m'?????1?xxx?3?[root@centos7?~]#?seq?3|sed?'N;s/1$/xxx/'??1?2?3?[root@centos7?~]#?seq?3|sed?'N;s/1$/xxx/M'?xxx?2? 3??D如果模式空間中沒有新行(如命令N產(chǎn)生的新行),則和命令d起同樣作用;如果包含新行,則會(huì)刪除第一行內(nèi)容,然后對(duì)模式空間中剩余內(nèi)容重新開始一輪處理。(注意:D后面的命令將會(huì)被忽略)
[root@centos7?~]#?seq?5|sed?'N;D'???5?[root@centos7?~]#?seq?5|sed?'N;N;D'????3?4? 5??P打印模式空間中第一行內(nèi)容
[root@centos7?~]#?seq?10|sed?-n?'N;P'??1?3?5?7?9?[root@centos7?~]#?seq?10|sed?-n?'N;N;P'?1?4?7?#注意另一種寫法輸出中的不同?[root@centos7?~]#?seq?10|sed?-n?'1~3P'??1?4?7? 10??g用保持空間中的內(nèi)容替換模式空間中的內(nèi)容
[root@centos7?~]#?seq?5|sed?-n?'g;N;s/\n/xx/p'?xx2?xx4? [root@centos7?~]#???G追加一個(gè)換行符到模式空間,然后再將保持空間中的內(nèi)容追加至換行符之后。(此時(shí)模式空間中內(nèi)容形如 PATTERN\nHOLD )
[root@centos7?~]#?seq?5|sed?'G;s/\n/xx/'???1xx?2xx?3xx?4xx? 5xx??h用模式空間中的內(nèi)容替換保持空間中的內(nèi)容(注意此時(shí)模式空間中的內(nèi)容并沒有被清除)
[root@centos7?~]#?seq?5|sed?-n?'h;G;s/\n/xx/p'?1xx1?2xx2?3xx3?4xx4?5xx5?[root@centos7?~]#?seq?5|sed?-n?'h;G;G;s/\n/xx/gp'?1xx1xx1?2xx2xx2?3xx3xx3?4xx4xx4? 5xx5xx5??H追加一個(gè)換行符到保持空間,然后再將模式空間中的內(nèi)容追加至換行符之后。(此時(shí)保持空間中內(nèi)容形如 HOLD\nPATTERN )
[root@centos7?~]#?seq?3|sed?-n?'H;G;s/\n/xx/gp'?1xxxx1?2xxxx1xx2?3xxxx1xx2xx3? [root@centos7?~]#???x交換模式空間和保持空間的內(nèi)容
[root@centos7?~]#?seq?9|sed?-n?'1!{x;N};s/\n//p'?3?25?47?69? #處于{...}之中的是命令組??: label為分支命令指定標(biāo)簽位置(不允許地址匹配)
b label無條件跳轉(zhuǎn)到label分支,如果省略了label,則跳轉(zhuǎn)到整條命令結(jié)尾(即開始下一次讀入)
#如刪除xml文件中注釋部分(<!?sed?'/<!--/{:a;/-->/!{N;ba};d}'?server.xml?#表示匹配<!?#如在nagios的配置文件中,有許多define?host{...}的字段,如下所示:?define?host{?use?windows-server?host_name?serverA?hostgroups?060202?alias?060202?contact_groups?yu?address?192.168.1.1?}?#現(xiàn)在需要?jiǎng)h除ip地址是192.168.1.1的段,可以這樣:?sed?-i?'/define?host/{:a;N;/}/!ba;/192\.168\.1\.1/d}'?file? #注意和前一個(gè)例子中的區(qū)別??t label在一次輸入后有成功執(zhí)行的s替換命令才跳轉(zhuǎn)到label,如果省略了label,則跳轉(zhuǎn)到整條命令結(jié)尾(即開始下一次讀入)
#如行列轉(zhuǎn)換?[root@centos7?~]#?seq?10|sed?':a;$!N;s/\n/,/;ta'?1,2,3,4,5,6,7,8,9,10?[root@centos7?~]#?#如將MAC地址78A35114F798改成帶冒號(hào)的格式78:A3:51:14:F7:98?[root@centos7?temp]#?echo?'78A35114F798'|sed?-r?':a;s/\B\w{2}\b/:&/;ta'?78:A3:51:14:F7:98?[root@centos7?temp]#?#這里\b表示匹配單詞邊界,\B表示匹配非單詞邊界的其他任意字符?#當(dāng)然也可以采用其他的方式實(shí)現(xiàn):?[root@centos7?temp]#?echo?'78A35114F798'|sed?-r?'s/..\B/&:/g'?78:A3:51:14:F7:98? [root@centos7?temp]#??T label在一次輸入后只要沒有替換命令被成功執(zhí)行就跳轉(zhuǎn)到label,如果省略了label,則跳轉(zhuǎn)到整條命令結(jié)尾(即開始下一次讀入)
z表示清除模式空間中內(nèi)容,和s/.*//起相同的作用,但更有效。
更多例子
1、刪除匹配行的上一行和下一行
#例如輸入數(shù)據(jù)為命令seq?10的輸出(當(dāng)然也可以是任意其他文件內(nèi)容)?#要求刪除匹配5那一行的前一行和后一行?[root@centos7?temp]#?seq?10|sed?-n?'$!N;/\n5/{s/.*\n//p;N;d};P;D'?1?2?3?5?7?8?9? 10??2、合并奇偶數(shù)行
#輸入數(shù)據(jù)為命令seq?11的輸出,要求分別將奇數(shù)和偶數(shù)分別放在同一行?#輸出第一行`1?3?5?7?9?11`,第二行`2?4?6?8?10`?[root@centos7?~]#?seq?11|sed?-nr?'$!N;2!G;s/([^\n]+)\n((.+)\n)?(.+)\n(.+)/\4?\1\n\5?\3/;h;$p'?1?3?5?7?9?11?2?4?6?8?10?? [root@centos7?~]#???3、合并多文件
#文本a.txt的內(nèi)容:?01?12510101?4001?02?12310001?4002?03?12550101?4003?04?12610001?4004?05?12810001?4005?06?12310001?4006?07?12710001?4007?08?12310001?4008?09?12810101?4009?10?12510101?4010?11?12310001?4011?12?12610001?4012?13?12310001?4013?#文本b.txt的內(nèi)容:?A?12410101?2006/02/15?2009/01/31?4002?B?12310001?2006/08/31?2008/08/29?4001?C?12610001?2008/05/23?2008/05/22?4002?D?12810001?1992/12/10?1993/06/30?4001?E?12660001?1992/05/11?1993/06/01?4005?#要求輸出a.txt內(nèi)容中第二列和b.txt中第二列相同的行,并追加b.txt中對(duì)應(yīng)的兩個(gè)日期列。?#形如:02?12310001?4002?2006/08/31?2008/08/29?sed?-rn?'/^[01]/ba;H;:a;G;s/^((..)(?.*)(?[^\n]+)).*\3((?[^?]*){2}).*/\1\5/p'?b.txt?a.txt?#當(dāng)然如果使用awk來處理的話,解決思路更容易理解一些:? awk?'NR==FNR{a[$2]=$3FS$4;next}{if($2?in?a)print?$0,a[$2]}'?b.txt?a.txt??為加深對(duì)sed各種命令特性的理解,請(qǐng)自行分析這三個(gè)例子。
各種命令的組合使用,再加上正則表達(dá)式的強(qiáng)大能力,使得sed可以處理所有能夠計(jì)算的問題。但由于代碼可讀性不強(qiáng),理解起來比較困難,通常使用sed作為一個(gè)文本編輯器,對(duì)文本做非交互的流式處理。理解上述各個(gè)命令的含義,熟練使用它們,就會(huì)發(fā)現(xiàn)sed的強(qiáng)大之處。
作者:vvpale 來源:51CTO
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的Linux基础命令介绍十:文本流编辑 sed的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。