本教程將介紹一些字串處理的重要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