sed 學習筆記

一  .  sed 簡介

1  .  功能
sed 是一種流編輯器,所謂流編輯器是指能夠對來自文件或者管道的輸入流進行基本的文本轉換的工具,比方說查找替換刪除等。

2  .  最簡單的運作機制

sed 程序運行時,會讀入腳本,然後把腳本作用在每一個輸入行上。
sed 在每個執行週期(excution cycle)裏完成以下任務:
1) 讀取下一行,行計數器加 1
2) 執行腳本
3) 一旦控制轉移到腳本末尾,自動輸出並清除模式空間的內容,進入下一個執行週期

注:
1) sed 每次都是從輸入流讀取下一行
2) 讀入一行都會刪除結尾的換行符再放入模式空間
3) 輸出模式空間內容時也會自動添加新行符

3  .  模式空間和保持空間(hold place)
模式空間就是一個數據緩衝區,特點是一旦控制到達腳本末尾,模式空間的內容會被自動清除。
保持空間也是一個數據緩衝區,其內容不會被自動清除,這非常有用。
模式空間與保持空間在 sed 程序開始之前初始化爲空。

二  .  sed 命令的定址

1  . 補充概念
1) 行計數器
已經從輸入流讀取的最後一行的行號,讀入新行會遞增
2) 美元符($)
輸入流的最後一行的行號($的含義受-s選項影響)

2  . 定址
可以爲sed腳本中每個指令指定一個條件,條件成立指令才能執行,無條件則直接執行。
條件分 "地址" 或 "地址範圍" 兩種。

地址有以下幾種形式:

NUMBER
表示 "行計數器爲 NUMBER" 這個條件

$
表示 "行計數器爲輸入流最後一行的行號" 這個條件

/REGEXP/
表示 "模式空間某部分能匹配REGEXP" 這個條件
REGEXP是正則表達式,須放在兩個分隔符(/)之間
欲匹配字面的/或者/,都要使用反斜槓(/)進行轉義
REGEXP末尾的$代表模式空間的結尾

/%REGEXP%
表示 "模式空間某部分能匹配REGEXP" 這個條件
REGEXP是正則表達式,須放在/%與%之間
適用於欲匹配大量字面/的情況,可編免大量地轉義/
分隔符還可以換爲其它字符

/REGEXP/I 或 /%REGEXP%I
表示 "模式空間某部分能不區分大小寫地匹配REGEXP" 這個條件
REGEXP是正則表達式,在/REGEXP/或/%REGEXP%之後添加I表示不區分大小寫
這是一個GNU擴展

/REGEXP/M 或 /%REGEXP%M
表示 "模式空間某部分能匹配REGEXP" 這個條件
但REGEXP開頭的 ^ 將匹配換行符之前的空串,而結尾的 $ 將匹配換行符之後的空串
這是一個GNU擴展


地址範圍通過在兩個地址之間添加一個逗號(comma)表示
籠統地講,地址範圍就四種形式,分別是
1)  正則式,行號
2)  正則式,正則式
3)  行號,行號
4)  行號,正則式
其中的正則式可以有/REGEXP/ 或 /%REGEXP% 等多種形式,這裏只採用/REGEXP/作爲例子:

/REGEXP/,NUMBER
這個地址範圍按如下方法匹配:從匹配REGEXP的行(包括此行)開始,持續到第NUMBER行(包括此行)。
如果找不到匹配REGEXP的行,則該地址範圍不匹配任何行。
若NUMBER小於或者等於第一個匹配REGEXP的行的行號,則該地址範圍只匹配該行;若NUMBER大於$(輸入流最後一行的行號),則該範圍會一直包括到輸入流的最後一行。


/REGEXP1/,/REGEXP2/
這個地址範圍按如下方法匹配:從匹配REGEXP1的行(包括此行)開始,持續到從該匹配行的下一行開始第一個匹配REGEXP2的行(包括此行)。
如果找不到匹配REGEXP1的行,則該地址範圍不匹配任何行。
如果在匹配REGEXP1的行後找不到匹配REGEXP2的行,則該地址範圍會一直包括到輸入流的最後一行(含此行)。

NUMBER,/REGEXP/
這個地址範圍按如下方法匹配:從第NUMBER(>=1)行開始(包括此行),持續到從第NUMBER行的下一行開始第一個匹配REGEXP的行(包括此行)。
如果NUMBER是個無效的行,則該地址範圍不包括任何行。
如果從第NUMBER行的下一行開始找不到匹配REGEXP的行,則該地址範圍會一直包括到輸入流的最後一行(含此行)。

NUMBER,NUMBER
這個地址範圍按如下方法匹配:從第NUMBER1行(包括此行)開始,持續到第NUMBER2行(包括此行)。
如果NUMBER1是個無效的行,則該地址範圍不包括任何行。
如果NUMBER2 <= NUMBER1 則該地址範圍只包括第NUMBER1 行。
如果NUMBER1是個有效行,但NUMBER2 > $ ,那該地址範圍將一直包括到輸入流的最後一行(包括此行)。


此外GNU擴展還有四種特殊的地址範圍表達方式,它們是 `0,/REGEXP/' 和`ADDR1,+N' 以及 `ADDR1,~N' 還有 `FIRST~STEP' 。

0,/REGEXP/
地址範圍使得REGEXP可以匹配第一行的內容

ADDR,+N
這個地址範圍按如下方法匹配:從滿足地址 ADDR 的行開始(含此行),一直到接下來的第 N 行(含此行),一共 N+1 行。
如果 ADDR 無效,則該地址範圍不包括任何行。
如果 ADDR 可以滿足,但 N 太大以至於超過了輸入流的最後一行,則該地址範圍將一直匹配到輸入流的最後一行(含最後一行)

ADDR,~N
這個地址範圍按如下方法匹配:從滿足地址 ADDR 的行開始(含此行),一直到該匹配行下面的第一個號行爲 N 的倍數的行(含此行)。
如果 ADDR 無效,則該地址範圍不包括任何行。
如果 ADDR 可以滿足,但匹配 ADDR 的哪一行之後沒有行號是 N 的倍數的行,則該地址範圍將一直包括到輸入流的最後一行(含最後一行)。

FIRST~STEP
這個地址範圍按如下方法匹配:找到第FIRST行(含此行), 按步長 STEP 找到該行之後所有的行。
如果FIRST 無效,則該地址範圍不包括任何行。

如果在地址或者地址範圍之後添加感嘆號(!)則表示與不加感嘆號相反的條件,例如$!表示"當前行計數器不是輸入流最後一行的行號"這個條件。

三  .  替換命令

替換命令的形式爲: s/REGEXP/REPLACEMENT/FLAGS
替換(substitude)命令的基本功能是在模式空間(pattern space)尋找匹配正則表達式REGEXP的部分,並替換成REPLACEMENT。
1  . FLAGS  只能是以下選項(option)

g
  指示 sed 將模式空間中匹配REGEXP的所有位置都替換成REPLACEMENT
NUMBERth
  指示 sed 只將模式空間中匹配REGEXP的第 NUMBERth 個位置替換成REPLACEMENT
p
  指示 sed 在完成模式空間的替換之後打印模式空間的內容到標準輸出,注意,如果沒有發生替換,那麼p 命令不執行。
w FILENAME
  指示 sed 在完成模式空間的替換之後打印模式空間的內容到文件 FILENAME ,注意,如果沒有發生替換,那麼w 命令不執行。
  FILENAME 支持兩個特殊的文件名 /dev/stderr 和 /dev/stdout 分別代表標準出錯和標準輸出,這是一個GNU擴展。
e
  指示 sed 在完成模式空間的替換之後,把模式空間的內容作爲命令執行,並把執行的結果寫到模式空間中。這是一個GNU擴展功能。
i 或 I
  指示 sed 在匹配REGEXP的時候忽略大小寫。這是一個GNU擴展功能。
m 或 M
  指示 sed 在匹配REGEXP的時候,用REGEXP首部的 ^ 匹配新行符之前的空串,用尾部的 $ 匹配新行符之後的空串。這是一個GNU擴展功能。

2  . REPLACEMENT

REPLACEMENT不是正則表達式,但是,在REPLACEMENT中出現的一些字符是有特殊含義的:
1)  & 代表模式空間中匹配REGEXP的部分,因此要在REPLACEMENT中表達字面&,需要用反斜槓轉義
2)  /number 是匹配REGEXP中第 number 對 /( 和 /) 之間的正則式的那部分字串。

3  . REGEXP

REGEXP 是正則式,如果想表達字面意義的字符,其中需要轉義的有:
1)  正則表達式的元字符
2)  斜槓(/),因爲 sed 的 s 命令認爲正則表達式REGEXP應該夾在兩個斜槓之間(/REGEXP/)

四  .   常用的 sed 指令

q
功能:
1)  將控制轉移到最後一條命令的後面
注意由於控制轉移到最後一條命令的後面,可能會有自動輸出。

n
功能:
1)  先輸出模式空間內容(前提:自動輸出沒有被屏蔽)
2)  讀入下一行,覆蓋模式空間,行計數器增 1
3)  控制轉移到下一條指令繼續執行。

p
功能:
1)  輸出模式空間內容
2)  控制轉移到下一條指令

d
功能:
1)  立刻清除模式空間內容
2)  把控制轉移到下一個週期的開始處繼續執行

N
功能:
1)  在當前模式空間內容之後添加新行符,然後讀入下一行,添在新行符之後,行計數器增1
2)  控制轉移到下一條指令繼續執行

P
功能:
1)  輸出模式空間左數第一個新行符前面的所有字符,以及該新行符
2)  控制轉移到下一條指令並繼續執行

D
功能:
1)  清除模式空間裏左數第一個新行符以及之前的所有字符
2)  如果清除過後模式空間不空,則控制轉移到下一個週期且不再讀入新行;否則控制轉移到下一個週期的開始處(這樣會讀入新行)。

=
功能:
1)  輸出行計數器的值並輸出新行符
這是一個GNU擴展

{ COMMANDS }
功能:
1)  把一組命令括在 { 和 } 之間,以便在某個條件下執行一組命令

y/CHAR_SET1/CHAR_SET2/
把模式空間中的包含在CHAR_SET1中的字符改爲CHAR_SET2中對應的字符

a/
TEXT
功能:
指出在週期末尾,自動輸出模式空間之後,把文本TEXT也輸出到標準輸出
約束:
1)  a 與 / 之間可以有 0 或以上的空格
2)  TEXT 中的每一行,除了最後一行,都要以反斜槓結尾以轉義新行符
3)  可以接受地址範圍,或者單獨的地址作爲執行條件
GNU擴展:
如果a之後的字符中有非空格字符,則從a之後第一個非空格字符開始的串會被作爲TEXT的第一行
如果第一行也是最後一行,則末尾無需加反斜槓以轉義新行符

i/
TEXT
功能:
立即把文本TEXT輸出到標準輸出
約束:
1)  i 與 / 之間可以有 0 或以上的空格
2)  TEXT 中的每一行,除了最後一行,都要以反斜槓結尾以轉義新行符
3)  只能接受地址範圍作爲執行條件
GNU擴展:
如果i之後的字符中有非空格字符,則從i之後第一個非空格字符開始的串會被作爲TEXT的第一行
如果第一行也是最後一行,則末尾無需加反斜槓以轉義新行符

r FILENAME
功能:
每個週期的自動輸出之前,把文件FILENAME的內容插入到輸出流並輸出。
如果FILENAME無法被讀取,則sed認爲它是一個空文件,無錯誤提示。
GNU擴展:
特殊串 /dev/stdin 被認爲是標準輸入

w FILENAME
功能:
將模式空間的內容寫入文件FILENAME
GNU擴展:
1)  特殊串/dev/stdout 和 /dev/stderr 分別表示標準輸出和標準出錯

五  .  模式空間與保持空間的互動

h
把模式空間的內容拷貝到保持空間

H
在保持空間內容末尾添加新行符,並把模式空間的內容拷貝到新行符之後

g
把保持空間的內容拷貝到模式空間

G
在模式空間的內容之後添加新行符,並把保持空間的內容拷貝到新行符之後

x
交換模式空間與保持空間的內容

六  .  sed 的選項

前面講解過 sed 的執行週期,我們知道,sed 每次從輸入流讀入一行,然後運行腳本,周而復始,直到讀入完畢。
-e 選項和 -f 選項 -s 選項涉及到腳本和輸入流的獲取:

-e  SCRIPT
 SCRIPT 是要在 sed 程序中執行的指令,sed 會把這些指令添加到指令序列之後
 
-f  SCRIPT_FILE
 SCRIPT_FILE 中存放着要在 sed 程序中執行的指令,sed 會把這些指令添加到指令序列之後

-s
 -s 是一個 GNU 擴展
 當命令行中出現多個輸入文件時,sed 默認會把所有文件的順序拼接作爲一個輸入流,在這種情況下,美元符號($)會被認爲是這個輸入流的最後一行,而地址範圍也可以跨越多個文件。如果想把命令的作用範圍限制在一個文件之內,則可以使用 -s 選項,此時,美元符($)就代表一個文件的結尾了,而行號則是相對於每個文件開頭的行數。

-n
 前面講過,控制轉移到腳本之後時,sed會自動輸出並清除模式空間的內容,-n選項能屏蔽這個動作:

七  .   sed 的分支命令

: LABEL
 用於在 sed 程序中設置一個標識位

b LABEL
 無條件將控制跳轉到(branch to分支到) LABEL 這個標識
 如果不指定 LABEL,則控制轉移到腳本之後。
 因此無LABEL的b導致:
 1)  如果自動輸出沒有被屏蔽,則輸出模式空間內容
 2)  進入下一個執行週期

t LABEL
 當 sed 的上一個替換命令(s)成功發生替換時,跳轉到 LABEL 這個標識
 如果不指定 LABEL,則控制跳轉到本週期末尾。
 因此無LABEL的t導致:
 1)  如果自動輸出沒有被屏蔽,則輸出模式空間內容
 2)  進入下一個執行週期


八. sed 實踐

1. unix 文本文件轉換爲 windows 格式文件

sed 's/$/\r/' unix.txt > win.txt

2.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章