Sed字符串
本教程將介紹一些字符串處理的重要sed命令。考慮我們有一個文本文件books.txt 要處理,它有以下內容:
- A Storm of Swords, George R. R. Martin, 1216
- The Two Towers, J. R. R. Tolkien, 352
- The Alchemist, Paulo Coelho, 197
- The Fellowship of the Ring, J. R. R. Tolkien, 432
- The Pilgrimage, Paulo Coelho, 288
- 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
執行上面的代碼,得到如下結果:
- A Storm of Swords | George R. R. Martin, 1216
- The Two Towers | J. R. R. Tolkien, 352
- The Alchemist | Paulo Coelho, 197
- The Fellowship of the Ring | J. R. R. Tolkien, 432
- The Pilgrimage | Paulo Coelho, 288
- A Game of Thrones | George R. R. Martin, 864
如果仔細觀察,只有第一個逗號替換,第二保持原樣。爲什麼呢?只要模式匹配,Sed 替換爲替換字符串並且移動到下一行。默認情況下,它僅替換第一次出現。要替換所有出現的,使用Sed全局標誌(g)如下:
[jerry]$ sed 's/,/ | /g' books.txt
執行上面的代碼,得到如下結果:
- A Storm of Swords | George R. R. Martin | 1216
- The Two Towers | J. R. R. Tolkien | 352
- The Alchemist | Paulo Coelho | 197
- The Fellowship of the Ring | J. R. R. Tolkien | 432
- The Pilgrimage | Paulo Coelho | 288
- A Game of Thrones | George R. R. Martin | 864
可以指示Sed執行文本替換,只有當一個模式匹配成功。下面的示例替換逗號(,)用豎線(|)僅當行包含模式。
[jerry]$ sed '/The Pilgrimage/ s/,/ | /g' books.txt
執行上面的代碼,得到如下結果:
- A Storm of Swords, George R. R. Martin, 1216
- The Two Towers, J. R. R. Tolkien, 352
- The Alchemist, Paulo Coelho, 197
- The Fellowship of the Ring, J. R. R. Tolkien, 432
- The Pilgrimage | Paulo Coelho | 288
- A Game of Thrones, George R. R. Martin, 864
Sed 也可以取代的模式發生的特定事件。替換逗號(,)以豎線的唯一的第二個實例(|)。下面是在sed命令(或標誌的地方),當前匹配的第二個出現的有多少。
[jerry]$ sed 's/,/ | /2' books.txt
執行上面的代碼,得到如下結果:
- A Storm of Swords, George R. R. Martin | 1216
- The Two Towers, J. R. R. Tolkien | 352
- The Alchemist, Paulo Coelho | 197
- The Fellowship of the Ring, J. R. R. Tolkien | 432
- The Pilgrimage,Paulo Coelho | 288
- A Game of Thrones, George R. R. Martin | 864
可以使用P標誌,如下打印不僅改變的行:
[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt
執行上面的代碼,得到如下結果:
- The Alchemist, PAULO COELHO, 197
- 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
執行上面的代碼,得到如下結果:
- The Alchemist, PAULO COELHO, 197
- The Pilgrimage, PAULO COELHO, 288
執行不區分大小寫的替換,可以使用i標誌,這意味着忽略大小寫。下面的例子執行不區分大小寫的替換。
[jerry]$ sed -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt
執行上面的代碼,得到如下結果:
- The Alchemist, PAULO COELHO, 197
- 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
執行上面的代碼,得到如下結果:
- The Alchemist, PAulo Coelho, 197
- The Pilgrimage, PAulo Coelho, 288
\u 標識
\u被替換字符串指定,它把後\u,如大寫字符前的字符。在下面的例子中,\u字符爲'a'和'o'之前使用。因此,Sed將這些字符轉爲大寫字母。
[jerry]$ sed -n 's/Paulo/p\uaul\uo/p' books.txt
執行上面的代碼,得到如下結果:
- The Alchemist, pAulO Coelho, 197
- The Pilgrimage, pAulO Coelho, 288
\U 標識
當\U在替換字符串中指定,把單詞的所有剩餘的字符\U後爲大寫字母。
[jerry]$ sed -n 's/Paulo/\Upaulo/p' books.txt
執行上面的代碼,得到如下結果:
- The Alchemist, PAULO Coelho, 197
- The Pilgrimage, PAULO Coelho, 288
\E 標識
\E標誌應使用\L或\U。它標誌\L或\U開始停止轉換。在下面的例子中,只有第一個字被替換爲大寫字母。
[jerry]$ sed -n 's/Paulo Coelho/\Upaulo \Ecoelho/p' books.txt
執行上面的代碼,得到如下結果:
- The Alchemist, PAULO coelho, 197
- The Pilgrimage, PAULO coelho, 288