您好,登錄后才能下訂單哦!
對于行處理的工具,sed絕對是首選的。
sed處理文本過程如下:
- sed一次處理一行內容,處理時,先讀入一行,去掉尾部換行符,存入pattern space,執行編輯命令.
- 處理完畢,除非加了-n參數,把現在的pattern space打印出來,在后邊打印曾去掉的換行符.
- 把pattern space內容給hold space,把pattern space置空,接著讀下一行,處理下一行.
這讓人感覺很抽象,sedsed的工具就是為了展現sed處理過程的。sedsed安裝和使用都很簡單,為了更好理解sed,裝上sedsed工具是很有必要的。
- wget http://aurelio.net/sedsed/sedsed-1.0
- touch /usr/local/bin/sedsed
- cat sedsed-1.0 >> /usr/local/bin/sedsed
- chmod 755 /usr/local/bin/sedsed
用法如下
- usage: sedsed OPTION [-e sedscript] [-f sedscriptfile] [inputfile]
- OPTIONS:
- -f, --file add file contents to the commands to be parsed
- -e, --expression add the script to the commands to be parsed
- -n, --quiet suppress automatic printing of pattern space
- --silent alias to --quiet
- -d, --debug debug the sed script
- --hide hide some debug info (options: PATT,HOLD,COMM)
- --color shows debug output in colors (default: ON)
- --nocolor no colors on debug output
- --dump-debug dumps to screen the debugged sed script
- --emu emulates GNU sed (INCOMPLETE)
- --emudebug emulates GNU sed debugging the sed script (INCOMPLETE)
- -i, --indent script beautifier, prints indented and
- one-command-per-line output do STDOUT
- --prefix indent prefix string (default: 4 spaces)
- -t, --tokenize script tokenizer, prints extensive
- command by command information
- -H, --htmlize converts sed script to a colorful HTML page
- -f選項和sed的-f選項一樣
- -d打開debug,其中--hide表示隱藏指定的內容;如--hide=hold表示隱藏的保留空間緩沖區的內容
- -i 的--indent 格式化復雜的sed腳本變成更加人性化的腳本
先看個簡單的例子:
[root@localhost ~]# cat 1.txt
linux
centos
redhat
linux
ubuntu
fedora
把linux換成debian,下面給出三種處理方式:sed處理;sedsed -d 和sedsed -d --hide
- [root@localhost ~]# sed 's/linux/debian/g' 1.txt
- debian
- centos
- redhat
- debian
- ubuntu
- fedora
- [root@localhost ~]# sedsed -d 's/linux/debian/g' 1.txt
- PATT:linux$
- HOLD:$
- COMM:s/linux/debian/g
- PATT:debian$
- HOLD:$
- debian
- PATT:centos$
- HOLD:$
- COMM:s/linux/debian/g
- PATT:centos$
- HOLD:$
- centos
- PATT:redhat$
- HOLD:$
- COMM:s/linux/debian/g
- PATT:redhat$
- HOLD:$
- redhat
- PATT:linux$
- HOLD:$
- COMM:s/linux/debian/g
- PATT:debian$
- HOLD:$
- debian
- PATT:ubuntu$
- HOLD:$
- COMM:s/linux/debian/g
- PATT:ubuntu$
- HOLD:$
- ubuntu
- PATT:fedora$
- HOLD:$
- COMM:s/linux/debian/g
- PATT:fedora$
- HOLD:$
- fedora
- [root@localhost ~]# sedsed -d --hide=hold 's/linux/debian/g' 1.txt
- PATT:linux$
- COMM:s/linux/debian/g
- PATT:debian$
- debian
- PATT:centos$
- COMM:s/linux/debian/g
- PATT:centos$
- centos
- PATT:redhat$
- COMM:s/linux/debian/g
- PATT:redhat$
- redhat
- PATT:linux$
- COMM:s/linux/debian/g
- PATT:debian$
- debian
- PATT:ubuntu$
- COMM:s/linux/debian/g
- PATT:ubuntu$
- ubuntu
- PATT:fedora$
- COMM:s/linux/debian/g
- PATT:fedora$
- fedora
其中:
PATT:sedsed輸出顯示模式空間緩沖區的內容
COMM:顯示正在執行的命令
HOLD:顯示hold sapce緩沖區的內容
sed的增刪改查
sed用于刪除操作的是:d和D
命令"d"作用是刪除模式空間的內容,然后讀入新的行,sed腳本從頭再次開始執行.
命令"D"的不同之處在于它刪除的是直到第一個內嵌換行符為止的模式空間的一部分,但是不會讀入新的行,腳本將回到開始對剩下內容進行處理.
看個例子
- [root@localhost ~]# cat 2.txt
- This line is followed by 1 blank line.
- This line is followed by 2 blank line.
- This line is followed by 3 blank line.
- This line is followed by 4 blank line.
- This is the end.
- [root@localhost ~]# sed '/^$/{N;/^\n$/D}' 2.txt
- This line is followed by 1 blank line.
- This line is followed by 2 blank line.
- This line is followed by 3 blank line.
- This line is followed by 4 blank line.
- This is the end.
- [root@localhost ~]# sed '/^$/{N;/^\n$/d}' 2.txt
- This line is followed by 1 blank line.
- This line is followed by 2 blank line.
- This line is followed by 3 blank line.
- This line is followed by 4 blank line.
- This is the end.
用sedsed 打開debug看看執行過程 //后面的內容是我注釋的
- [root@localhost ~]# sedsed -d '/^$/{N;/^\n$/D}' 2.txt
- PATT:This line is followed by 1 blank line.$ //pattern空間讀入第一行內容
- HOLD:$ //hold空間開始為空
- COMM:/^$/ { //正在執行的命令,判斷是否為空行,很明顯不是,所有不執行后面的命令,執行的結果送往屏幕并把結果給hold space.
- PATT:This line is followed by 1 blank line.$
- HOLD:$
- This line is followed by 1 blank line.
- PATT:$ //pattern空間讀入第二行
- HOLD:$ //hold空間開始還是為空
- COMM:/^$/ { //正在執行的命令,判斷是否為空行,很明顯是,所有執行后面的命令
- COMM:N //執行N讀取下一行進入pattern空間
- PATT:\nThis line is followed by 2 blank line.$
- HOLD:$ //此時hold空間還是為空
- COMM:/^\n$/ D //對pattern空間繼續執行后面的命令:如果是空行,執行D命令,很明顯不是,所有不執行。
- PATT:\nThis line is followed by 2 blank line.$ //pattern空間內容
- HOLD:$ //hold空間內容,任然為空。
- COMM:}
- PATT:\nThis line is followed by 2 blank line.$
- HOLD:$
- This line is followed by 2 blank line. //由于沒有滿足執行條件,繼續讀取下一行。
- PATT:$ //空行,滿足執行條件,執行命令
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ D //滿足執行D命令條件,刪除一空行(現在有兩空行)
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\nThis line is followed by 3 blank line.$
- HOLD:$
- COMM:/^\n$/ D
- PATT:\nThis line is followed by 3 blank line.$
- HOLD:$
- COMM:}
- PATT:\nThis line is followed by 3 blank line.$
- HOLD:$
- This line is followed by 3 blank line.
- PATT:$ \\空行,滿足命令執行條件,執行命令,讀取下一行.
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ D \\滿足執行D命令,刪除一空行.
- PATT:$ \\空行,滿足命令執行條件,執行命令,讀取下一行.
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ D \\ \\滿足執行D命令,刪除一空行.
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\nThis line is followed by 4 blank line.$
- HOLD:$
- COMM:/^\n$/ D
- PATT:\nThis line is followed by 4 blank line.$
- HOLD:$
- COMM:}
- PATT:\nThis line is followed by 4 blank line.$
- HOLD:$
- This line is followed by 4 blank line.
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ D
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ D
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ D
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\nThis is the end.$
- HOLD:$
- COMM:/^\n$/ D
- PATT:\nThis is the end.$
- HOLD:$
- COMM:}
- PATT:\nThis is the end.$
- HOLD:$
- This is the end.
- [root@localhost ~]# sedsed -d '/^$/{N;/^\n$/d}' 2.txt
- PATT:This line is followed by 1 blank line.$
- HOLD:$
- COMM:/^$/ {
- PATT:This line is followed by 1 blank line.$
- HOLD:$
- This line is followed by 1 blank line.
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\nThis line is followed by 2 blank line.$
- HOLD:$
- COMM:/^\n$/ d
- PATT:\nThis line is followed by 2 blank line.$
- HOLD:$
- COMM:}
- PATT:\nThis line is followed by 2 blank line.$
- HOLD:$
- This line is followed by 2 blank line.
- PATT:$ \\空行,滿足命令執行條件,執行命令,讀取下一行.
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ d \\滿足執行d命令條件,此時模式空間的兩個空行都被刪除.
- PATT:This line is followed by 3 blank line.$
- HOLD:$
- COMM:/^$/ {
- PATT:This line is followed by 3 blank line.$
- HOLD:$
- This line is followed by 3 blank line.
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ d
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\nThis line is followed by 4 blank line.$
- HOLD:$
- COMM:/^\n$/ d
- PATT:\nThis line is followed by 4 blank line.$
- HOLD:$
- COMM:}
- PATT:\nThis line is followed by 4 blank line.$
- HOLD:$
- This line is followed by 4 blank line.
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ d
- PATT:$
- HOLD:$
- COMM:/^$/ {
- COMM:N
- PATT:\n$
- HOLD:$
- COMM:/^\n$/ d
- PATT:This is the end.$
- HOLD:$
- COMM:/^$/ {
- PATT:This is the end.$
- HOLD:$
- This is the end.
一般情況下,都用d來刪除,如:
- 刪除空行:
- sed '/^\s*$/d' filename
- sed '/^[[:space:]]*$/d' filename
- 用行標示號來刪除
- sed 'n1d' filename 刪除第n1行
- sed 'n1,n2d' filename 刪除第n1行到n2行間內容(n1<=n2)
- sed '5,$d' filename 刪除第5行以后內容內容
- 用特殊匹配來刪除,格式如下
- sed '/regular_pattern/d' filename
sed基于行的插入和替換操作是由:a\,i\,c\來完成
- a\命令是追加命令,追加將添加新文本到文件中當前行(即讀入模式緩沖區中的行)的后面.所追加的文本行位于sed命令的下方另起一行.如果要追加的內容超過一行,則每一行都必須以反斜線結束,最后一行除外.最后一行將以引號和文件名結束.
- i\ 命令是在當前行的前面插入新的文本.
- c\ 用新的文本改變本行的文本
a\和i\用法比較簡單,看一個c\的例子
- [root@localhost ~]# cat 1.txt
- linux
- centos
- redhat
- linux
- ubuntu linux
- fedora
- [root@localhost ~]# sedsed -d '/linux/c\unix' 1.txt
- PATT:linux$
- HOLD:$
- COMM:/linux/ c\\N\unix
- unix
- PATT:centos$
- HOLD:$
- COMM:/linux/ c\\N\unix
- PATT:centos$
- HOLD:$
- centos
- PATT:redhat$
- HOLD:$
- COMM:/linux/ c\\N\unix
- PATT:redhat$
- HOLD:$
- redhat
- PATT:linux$
- HOLD:$
- COMM:/linux/ c\\N\unix
- unix
- PATT:ubuntu linux$
- HOLD:$
- COMM:/linux/ c\\N\unix
- unix
- PATT:fedora$
- HOLD:$
- COMM:/linux/ c\\N\unix
- PATT:fedora$
- HOLD:$
- fedora
sed的替換操作是用的最多的,用sed處理內容,最重要的就是要找特征數據(字符),并以此為基礎處理內容而不會處理的內容過多或者處理不完全.
如最開始的舉的把linux換成debian的例子.
sed 的高級運用
打印匹配行號
- [root@localhost ~]# cat 1.txt
- linux
- centos
- redhat
- linux
- ubuntu linux
- fedora
- [root@localhost ~]# sed -n '/^linux/=' 1.txt
- 1
- 4
- [root@localhost ~]# sed -n '/^linux/{=;p}' 1.txt
- 1
- linux
- 4
- linux
- [root@localhost ~]# sedsed -d -n '/^linux/{=;p}' 1.txt
- PATT:linux$
- HOLD:$
- COMM:/^linux/ {
- COMM:=
- 1
- PATT:linux$
- HOLD:$
- COMM:p
- linux
- PATT:linux$
- HOLD:$
- COMM:}
- PATT:linux$
- HOLD:$
- PATT:centos$
- HOLD:$
- COMM:/^linux/ {
- PATT:centos$
- HOLD:$
- PATT:redhat$
- HOLD:$
- COMM:/^linux/ {
- PATT:redhat$
- HOLD:$
- PATT:linux$
- HOLD:$
- COMM:/^linux/ {
- COMM:=
- 4
- PATT:linux$
- HOLD:$
- COMM:p
- linux
- PATT:linux$
- HOLD:$
- COMM:}
- PATT:linux$
- HOLD:$
- PATT:ubuntu linux$
- HOLD:$
- COMM:/^linux/ {
- PATT:ubuntu linux$
- HOLD:$
- PATT:fedora$
- HOLD:$
- COMM:/^linux/ {
- PATT:fedora$
- HOLD:$
- [root@localhost ~]# sedsed -d '/^linux/{=;p}' 1.txt
- PATT:linux$
- HOLD:$
- COMM:/^linux/ {
- COMM:=
- 1
- PATT:linux$
- HOLD:$
- COMM:p
- linux
- PATT:linux$
- HOLD:$
- COMM:}
- PATT:linux$
- HOLD:$
- linux
- PATT:centos$
- HOLD:$
- COMM:/^linux/ {
- PATT:centos$
- HOLD:$
- centos
- PATT:redhat$
- HOLD:$
- COMM:/^linux/ {
- PATT:redhat$
- HOLD:$
- redhat
- PATT:linux$
- HOLD:$
- COMM:/^linux/ {
- COMM:=
- 4
- PATT:linux$
- HOLD:$
- COMM:p
- linux
- PATT:linux$
- HOLD:$
- COMM:}
- PATT:linux$
- HOLD:$
- linux
- PATT:ubuntu linux$
- HOLD:$
- COMM:/^linux/ {
- PATT:ubuntu linux$
- HOLD:$
- ubuntu linux
- PATT:fedora$
- HOLD:$
- COMM:/^linux/ {
- PATT:fedora$
- HOLD:$
- fedora
上面sedsed的調試顯示了sed -n的參數的實際實現:禁止自動打印模式空間內容.
sed 多行處理
- sed多行處理是通過n和N來實現
- 多行Next(N)命令是相對next(n)命令的,后者將模式空間中的內容輸出,然后把下一行讀入模式空間,但是腳本并不會轉移到開始而是從當前的n命令之后開始執行; 而前者則保存原來模式空間中的內容,再把新的一行讀入,兩者之間依靠一個換行符"\n"來分隔。在N命令執行后,控制流將繼續用N命令以后的命令對模式空間進行處理.
- 值得注意的是,在多行模式中,特殊字符"^"和"$"匹配的是模式空間的最開始與最末尾,而不是內嵌"\n"的開始與末尾.
如下現在要將"Owner and Operator Guide"替換為"Installation Guide":
- [root@localhost ~]# cat 3.txt
- Consult Section 3.1 in the Owner and Operator
- Guide for a description of the tape drives
- available on your system.
- [root@localhost ~]# sedsed -d --hide=hold '/Operator$/{n;s/Owner and Operator\nGuide /Installation Guide\n/}' 3.txt
- PATT:Consult Section 3.1 in the Owner and Operator$
- COMM:/Operator$/ {
- COMM:n
- Consult Section 3.1 in the Owner and Operator
- PATT:Guide for a description of the tape drives$
- COMM:s/Owner and Operator\nGuide /nstallation Guide\n/
- PATT:Guide for a description of the tape drives$
- COMM:}
- PATT:Guide for a description of the tape drives$
- Guide for a description of the tape drives
- PATT:available on your system.$
- COMM:/Operator$/ {
- PATT:available on your system.$
- available on your system.
- [root@localhost ~]# sedsed -d --hide=hold '/Operator$/{N;s/Owner and Operator\nGuide /Installation Guide\n/}' 3.txt
- PATT:Consult Section 3.1 in the Owner and Operator$
- COMM:/Operator$/ {
- COMM:N
- PATT:Consult Section 3.1 in the Owner and Operator\nGuide for a descr\
- iption of the tape drives$
- COMM:s/Owner and Operator\nGuide /nstallation Guide\n/
- PATT:Consult Section 3.1 in the nstallation Guide\nfor a description \
- of the tape drives$
- COMM:}
- PATT:Consult Section 3.1 in the nstallation Guide\nfor a description \
- of the tape drives$
- Consult Section 3.1 in the nstallation Guide
- for a description of the tape drives
- PATT:available on your system.$
- COMM:/Operator$/ {
- PATT:available on your system.$
- available on your system.
sed用于把文本讀入模式空間或者模式空間的內容寫入到指定文本中.
sed把模式空間的內容寫入到指定文本中:由w和W實現
w filename:Write the current pattern space to filename.
W filename:Write the first line of the current pattern space to filename.
如下:
- [root@localhost ~]# cat 1.txt
- linux server
- centos
- redhat
- linux web
- ubuntu linux
- fedora
- [root@localhost ~]# sed -n '/^linux/,/^linux/w a.txt' 1.txt
- [root@localhost ~]# cat a.txt
- linux server
- centos
- redhat
- linux web
sed把文本讀入模式空間由r實現
- [root@localhost ~]# cat 1.txt
- linux server
- centos
- redhat
- linux web
- ubuntu linux
- fedora
- [root@localhost ~]# sed '/centos/r /root/1.txt' 1.txt
- linux server
- centos
- linux server
- centos
- redhat
- linux web
- ubuntu linux
- fedora
- redhat
- linux web
- ubuntu linux
- fedora
sed高級流控制
- b 分支:無條件轉移 ,分支到腳本中帶有標記的地方,如果分支不存在則分支到腳本的末尾.
- t 有條件的轉移,if分支,從最后一行開始,條件一旦滿足或者T,t命令,將導致分支到帶有標號的命令處,或者到腳本的末尾.
- T 有條件的轉移,錯誤分支,從最后一行開始,一旦發生錯誤或者T,t命令,將導致分支到帶有標號的命令處,或者到腳本的末尾.
[root@localhost ~]# cat 4.txt
a b c a d a a a
s d d d x s a
h j s a s h j h
j d f j a s j k j
要求:刪除行內與第一列字符重復的字符,shell、sed、awk各寫一個。達到這個結果:
a b c d
s d d d x a
h j s a s j
j d f a s k
這個例子來自http://blog.chinaunix.net/uid-10540984-id-3086644.html
- [root@localhost ~]# sed ':a;s/^\(.\)\(.*\) \1/\1\2/;ta' 4.txt
- a b c d
- s d d d x a
- h j s a s j
- j d f a s k
- [root@localhost ~]# sedsed -d --hide=hold ':a;s/^\(.\)\(.*\) \1/\1\2/;ta' 4.txt
- PATT:a b c a d a a a$
- COMM::a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:a b c a d a a$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:a b c a d a$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:a b c a d$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:a b c d$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:a b c d$
- COMM:t a
- PATT:a b c d$
- a b c d
- PATT:s d d d x s a$
- COMM::a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:s d d d x a$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:s d d d x a$
- COMM:t a
- PATT:s d d d x a$
- s d d d x a
- PATT:h j s a s h j h$
- COMM::a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:h j s a s h j$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:h j s a s j$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:h j s a s j$
- COMM:t a
- PATT:h j s a s j$
- h j s a s j
- PATT:j d f j a s j k j$
- COMM::a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:j d f j a s j k$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:j d f j a s k$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:j d f a s k$
- COMM:t a
- COMM:s/^\(.\)\(.*\) \1/\1\2/
- PATT:j d f a s k$
- COMM:t a
- PATT:j d f a s k$
- j d f a s k
- 附加兩種其他的解法
- while read a b;do echo "$a ${b// $a}";done <4.txt
- awk '{a=$1;gsub(" ?"a,"");print a""$0}' 4.txt
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。