流編輯器 - 字串



替換命令

文字替換操作(如“查詢和替換”)在任何文字編輯器中都很常見。在本節中,我們將說明 SED 如何執行文字替換。以下是替換命令的語法。

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

這裡,address1address2 分別是起始地址和結束地址,可以是行號或模式字串。這兩個地址都是可選引數。模式是我們想要用替換字串替換的文字。此外,我們還可以使用 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 僅在模式匹配成功時執行文字替換。以下示例僅當一行包含模式 The Pilgrimage 時,才將逗號 (,) 替換為豎線 (|)。

[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 可以替換模式的特定匹配項。讓我們只用豎線 (|) 替換逗號 (,) 的第二個例項。

[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

在上面的示例中,SED 命令末尾的數字(或標誌所在的位置)表示第二個匹配項。

SED 提供了一個有趣的特性。執行替換後,SED 提供了一個選項,僅顯示已更改的行。為此,SED 使用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

我們使用了相同的 SED 命令。讓我們驗證一下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

到目前為止,我們只使用正斜槓 (/) 字元作為分隔符,但我們也可以使用豎線 (|)、at 符號 (@)、脫字元 (^)、感嘆號 (!) 作為分隔符。以下示例演示瞭如何使用其他字元作為分隔符。

假設您需要將路徑/bin/sed替換為/home/jerry/src/sed/sed-4.2.2/sed。因此,您的 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

確實!我們得到了相同的結果,並且語法更具可讀性。類似地,我們可以使用“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 

通常,反斜槓 (/) 用作分隔符,但有時使用 SED 支援的其他分隔符會更方便。

建立子字串

我們學習了強大的替換命令。讓我們看看是否可以從匹配的文字中找到子字串。讓我們透過一個示例瞭解如何做到這一點。

讓我們考慮以下文字

[jerry]$ echo "Three One Two"

假設我們必須將其排列成一個序列。意思是,它應該首先列印 One,然後列印 Two,最後列印 Three。以下單行程式碼可以滿足需要。

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

請注意,在上面的示例中,豎線 (|) 用作分隔符。

在 SED 中,可以透過使用分組運算子來指定子字串,並且必須以跳脫字元為字首,即\(\)

\w是一個正則表示式,它匹配任何字母、數字或下劃線,並且“+”用於匹配多個字元。換句話說,正則表示式\(\w\+\)匹配輸入字串中的單個單詞。

在輸入字串中,有三個單詞用空格分隔,因此有三個用空格分隔的正則表示式。第一個正則表示式儲存第一個單詞,即 Three,第二個儲存單詞One,第三個儲存單詞Two

這些子字串由\N引用,其中 N 是子字串編號。因此,\2列印第二個子字串,即One;\3列印第三個子字串,即Two;\1列印第一個子字串,即Three

讓我們用逗號 (,) 分隔這些單詞,並相應地修改正則表示式。

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

執行上述程式碼後,您將得到以下結果

One,Two,Three

請注意,現在正則表示式中使用逗號 (,) 代替空格。

字串替換標誌(僅限 GNU SED)

在上一節中,我們看到了替換命令的一些示例。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:此標誌應與 \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
廣告