Linux常用命令09 - sed

在處理文本文件時,通常需要在一個或多個文件中查找和替換文本字符串。

sed 是一個流編輯器。 它可以對文件和輸入流(如管道)執行基本的文本操作。 使用 sed,您可以搜索、查找和替換、插入和刪除單詞和行。 它支持基本的和擴展的正則表達式,允許您匹配複雜的模式。

接下來, 我將使用 sed 查找和替換字符串。 我還將向您展示如何執行遞歸搜索和替換。

查找和替換字符串sed

sed 有幾個版本,它們之間有一些函數上的差異。 Macos 使用的是 BSD 版本,而且大多數 Linux 發行版默認都預裝了 GNU。 下面默認的是 GNU 版本。

使用 sed 搜索和替換文本的一般形式如下:

sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE
  • -i 將其輸出寫入標準輸出sed
  • s 替代命令,可能是 sed 中使用最多的命令
    -/分隔符字符。它可以是任何字符,但通常是斜槓(/) 字符
  • SEARCH_REGEX 要搜索的普通字符串或正則表達式
  • REPLACEMENT 替換字符串
  • g 全局替換標誌。默認情況下一行一行地讀取文件,只更改第一次出現的SEARCH_REGEX,當提供替換標誌時,所有出現的情況都將被替換
  • INPUTFILE 要在其上運行命令的文件名
    最好在參數周圍加上引號,這樣 shell 元字符就不會擴展。

讓我看一些示例,說明如何使用 sed 命令搜索文件中的文本,並使用其中一些最常用的選項和標誌替換文件中的文本。

爲了便於演示,我將使用以下文件 file.txt:


123 Foo foo foo 
foo /bin/bash Ubuntu foobar 456

如果省略了 g 標誌,那麼每行中搜索字符串的第一個實例將被替換:

sed -i '' 's/foo/linux/' file.txt

123 Foo linux foo 

linux /bin/bash Ubuntu foobar 456

I1CZtI
使用全局替換標誌 sed 替換所有出現的搜索模式:

sed -i '' 's/foo/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456

XSP3mF

正如您可能已經注意到的,在前面的示例中,foobar 字符串中的子字符串 foo 也被替換了。 如果這不是想要的行爲,請在搜索字符串的兩端使用單詞邊界表達式(\b)。 這將確保部分詞不匹配。

sed -i  's/\bfoo\b/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu foobar 456

lCjovE

若要使模式匹配不區分大小寫,請使用 I 標誌。 在下面的例子中,我同時使用了 g 和 I 標誌:

sed -i  's/foo/linux/gI' file.txt
123 linux linux linux 
linux /bin/bash Ubuntu linuxbar 456

如果要查找和替換包含分隔符(/)的字符串,則需要使用反斜槓(\)來轉義斜槓。 例如,用/usr/bin/zsh 替換/bin/bash

sed -i '' 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txt

更簡單和更易讀的選項是使用另一個分隔符字符。 大多數人使用豎線(|)或冒號(😃 ,但你可以使用任何其他字符:

sed -i 's|/bin/bash|/usr/bin/zsh|g' file.txt
123 Foo foo foo 
foo /usr/bin/zsh Ubuntu foobar 456

您還可以使用正則表達式。 例如,搜索所有的3位數字,並將它們替換爲您將使用的字符串數字:

sed -i 's/\b[0-9]\{3\}\b/number/g' file.txt
number Foo foo foo 
foo /bin/bash demo foobar number

sed 的另一個有用特性是,您可以使用與匹配模式相對應的 & 符號。 該字符可以被多次使用。

例如,如果要在每個3位數字周圍加上大括號{} ,請鍵入:

sed -i 's/\b[0-9]\{3\}\b/{&}/g' file.txt
{123} Foo foo foo 
foo /bin/bash demo foobar {456}

最後但並非最不重要的一點是,在使用 sed 編輯文件時進行備份總是一個好主意。 要做到這一點,只需要爲 -i 選項提供一個擴展。 例如,要編輯 file.txt 並將原始文件保存爲 file.txt.bak,可以使用:

sed -i.bak 's/foo/linux/g' file.txt

如果你想確保備份已經創建,用 ls 命令列出文件:

ls
file.txt file.txt.bak

遞歸查找和替換

有時,您希望遞歸地搜索目錄中包含字符串的文件,並替換所有文件中的字符串。 這可以通過使用 find 或 grep 等命令遞歸地查找目錄中的文件並將文件名管道化爲 sed 來實現。

下面的命令將遞歸搜索當前工作目錄文件夾中的文件,並將文件名傳遞給 sed。

find . -type f -exec sed -i 's/foo/bar/g' {} +

爲了避免文件名中包含空格的問題,可以使用-print0選項,它告訴 find 打印文件名,然後使用空字符,並使用 xargs-0將輸出管道傳送到 sed:

find . -type f -print0 | xargs -0 sed -i 's/foo/bar/g'

要排除目錄,請使用非路徑選項。 例如,如果您正在替換本地 git repo 中的字符串,以排除所有以點(.)開頭的文件 、使用:

find . -type f -not -path '*/\.*' -print0 | xargs -0 sed -i 's/foo/bar/g'

如果你只想搜索和替換具有特定擴展名的文件中的文本,你可以使用:

find . -type f -name "*.md" -print0 | xargs -0 sed -i 's/foo/bar/g'

另一種選擇是使用 grep 命令遞歸地查找包含搜索模式的所有文件,然後將文件名通過管道傳遞給 sed:

grep -rlZ 'foo' . | xargs -0 sed -i.bak 's/foo/bar/g'

小結

雖然它看起來複雜和複雜,但實際上,用 sed 在文件中搜索和替換文本非常簡單。

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