Sed字串


本教學將介紹一些字串處理的重要sed命令。考慮我們有一個文字檔案books.txt 要處理,它有以下內容:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

替換命令

“查詢和替換”文字替換操作字串最常見。下面給出的是替換命令的語法:

[address1[,address2]]s/pattern/replacement/[flags]

這裡,address1 和 address2分別是起始和結束地址,它可以是行號或模式串。這兩個地址是可選引數。

該模式是要替換的替換字串的字串。此外,也可以指定可選的標誌,以增強功能。

以下是 sed 命令替換所有books.txt 用逗號與豎線(|)。

[jerry]$ sed 's/,/ | /' books.txt

執行上面的程式碼,得到如下結果:

1) A Storm of Swords |  George R. R. Martin, 1216
2) The Two Towers |  J. R. R. Tolkien, 352
3) The Alchemist |  Paulo Coelho, 197
4) The Fellowship of the Ring |  J. R. R. Tolkien, 432
5) The Pilgrimage |  Paulo Coelho, 288
6) A Game of Thrones |  George R. R. Martin, 864

如果仔細觀察,只有第一個逗號替換,第二保持原樣。為什麼呢?只要模式匹配,Sed 替換為替換字串並且移動到下一行。預設情況下,它僅替換第一次出現。要替換所有出現的,使用Sed全域性標誌(g)如下:

[jerry]$ sed 's/,/ | /g' books.txt

執行上面的程式碼,得到如下結果:

1) A Storm of Swords |  George R. R. Martin |  1216
2) The Two Towers |  J. R. R. Tolkien |  352
3) The Alchemist |  Paulo Coelho |  197
4) The Fellowship of the Ring |  J. R. R. Tolkien |  432
5) The Pilgrimage |  Paulo Coelho |  288
6) A Game of Thrones |  George R. R. Martin |  864

可以指示Sed執行文字替換,只有當一個模式匹配成功。下面的範例替換逗號(,)用豎線(|)僅當行包含模式。

[jerry]$ sed '/The Pilgrimage/ s/,/ | /g' books.txt 

執行上面的程式碼,得到如下結果:

1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage | Paulo Coelho | 288 
6) A Game of Thrones, George R. R. Martin, 864

Sed 也可以取代的模式發生的特定事件。替換逗號(,)以豎線的唯一的第二個範例(|)。下面是在sed命令(或標誌的地方),當前匹配的第二個出現的有多少。

[jerry]$ sed 's/,/ | /2' books.txt

執行上面的程式碼,得到如下結果:

1) A Storm of Swords, George R. R. Martin | 1216 
2) The Two Towers, J. R. R. Tolkien | 352 
3) The Alchemist, Paulo Coelho | 197 
4) The Fellowship of the Ring, J. R. R. Tolkien | 432 
5) The Pilgrimage,Paulo Coelho | 288 
6) A Game of Thrones, George R. R. Martin  | 864

可以使用P標誌,如下列印不僅改變的行:

[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt

執行上面的程式碼,得到如下結果:

3) The Alchemist, PAULO COELHO, 197 
5) The Pilgrimage, PAULO COELHO, 288 

可以在另一個檔案中儲存更改的行。為了實現這種結果,可以使用 w 標誌如下所示:

[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/w junk.txt' books.txt

現在 junk.txt 檔案已全部更改的檔案。讓我們驗證 junk.txt 檔案的內容。

[jerry]$ cat junk.txt

執行上面的程式碼,得到如下結果:

3) The Alchemist, PAULO COELHO, 197 
5) The Pilgrimage, PAULO COELHO, 288

執行不區分大小寫的替換,可以使用i標誌,這意味著忽略大小寫。下面的例子執行不區分大小寫的替換。

[jerry]$ sed  -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt

執行上面的程式碼,得到如下結果:

3) The Alchemist, PAULO COELHO, 197 
5) The Pilgrimage, PAULO COELHO, 288

非標分隔符

通常,反斜槓(/)作為分隔符,但有時是用其它支援定界符以用 sed 更方便。

到目前為止,我們已經使用了只有反斜槓(/)字元作為分隔符,但我們也可以使用豎線(|),at符號(@),插入符號(^),感嘆號作為分隔符(!)。下面的範例演示了如何使用其他字元作為分隔符。

下面的例子使用豎線(|)作為分隔符:

[jerry]$ echo "/bin/sed" | sed 's|/bin/sed|/home/jerry/src/sed/sed-4.2.2/sed|'

執行上面的程式碼,得到如下結果:

/home/jerry/src/sed/sed-4.2.2/sed

同樣,我們可以用“at”符號(@)使用作為分隔符,如下所示:

[jerry]$ echo "/bin/sed" | sed 's@/bin/sed@/home/jerry/src/sed/sed-4.2.2/sed@'

執行上面的程式碼,得到如下結果:

/home/jerry/src/sed/sed-4.2.2/sed 

同樣,我們可以使用插入符號(^)作為分隔符,如下所示:

[jerry]$ echo "/bin/sed" | sed 's^/bin/sed^/home/jerry/src/sed/sed-4.2.2/sed^'

執行上面的程式碼,得到如下結果:

/home/jerry/src/sed/sed-4.2.2/sed 

同樣,我們可以使用感嘆號作為分隔符如下(!):

[jerry]$ echo "/bin/sed" | sed 's!/bin/sed!/home/jerry/src/sed/sed-4.2.2/sed!'

執行上面的程式碼,得到如下結果:

/home/jerry/src/sed/sed-4.2.2/sed 

建立一個子串

我們學到了強大的替換命令。看看是否可以找到一個匹配的文字字串。了解如何用一個例子來說明。

看看下面的文字:

[jerry]$ echo "Three One Two"

假設我們要安排成一個序列。意味著,它應該列印一份,再兩個,最後三個。下面的單行程式碼執行。

[jerry]$ echo "Three One Two" | sed 's|\(\w\+\) \(\w\+\) \(\w\+\)|\2 \3 \1|'

sed 子串可以通過使用分組操作員指定,並且它必須以跳脫字元作為字首,即\(和\)。

在這裡,\ w是一個正規表示式匹配任何字母或下劃線和“+”號來匹配多個字元。換句話說,正規表示式 \(\w\+\)從輸入串中的單個字相匹配。

這個子串由\N,N是子串號轉介。因此,\2列印第二子串,即一個; \3列印第三子串,即兩種;和\1列印第一子,即Three

讓我們分開這些話通過逗號(,)並相應修改則表示式。

[jerry]$ echo "Three,One,Two" | sed 's|\(\w\+\),\(\w\+\),\(\w\+\)|\2,\3,\1|'

執行上面的程式碼,得到如下結果:

One,Two,Three

字串替換標誌

GNU Sed 提供可在替換字串中使用一些特殊的跳脫序列。請注意,這些字串替換標誌是GNU具體指定,可能無法與Sed其他變種進行工作。在這裡,我們將討論的字串替換標誌。

 \L 標識

當在替換字串中指定\L,它把該單詞的所有剩餘的字元,\L以小寫字元。例如,字元“ULO”被視為小寫字元。

[jerry]$ sed -n 's/Paulo/PA\LULO/p' books.txt

執行上面的程式碼,得到如下結果:

3) The Alchemist, PAulo Coelho, 197
5) The Pilgrimage, PAulo Coelho, 288

\u 標識

\u被替換字串指定,它把後\u,如大寫字元前的字元。在下面的例子中,\u字元為'a'和'o'之前使用。因此,Sed將這些字元轉為大寫字母。

[jerry]$ sed -n 's/Paulo/p\uaul\uo/p' books.txt

執行上面的程式碼,得到如下結果:

3) The Alchemist, pAulO Coelho, 197 
5) The Pilgrimage, pAulO Coelho, 288

\U 標識

當\U在替換字串中指定,把單詞的所有剩餘的字元\U後為大寫字母。

[jerry]$ sed -n 's/Paulo/\Upaulo/p' books.txt 

執行上面的程式碼,得到如下結果:

3) The Alchemist, PAULO Coelho, 197 
5) The Pilgrimage, PAULO Coelho, 288

 \E 標識

\E標誌應使用\L或\U。它標誌\L或\U開始停止轉換。在下面的例子中,只有第一個字被替換為大寫字母。

[jerry]$ sed -n 's/Paulo Coelho/\Upaulo \Ecoelho/p' books.txt

執行上面的程式碼,得到如下結果:

3) The Alchemist, PAULO coelho, 197 
5) The Pilgrimage, PAULO coelho, 288