如何在 Linux 使用 sed 查找和替换文件字符串
sed 是一个轻量级 stream 流编辑器。它可以对文件和输入流执行基本的文本操作
sed 是一个轻量级 stream 流编辑器。它可以对文件和输入流(例如管道)执行基本的文本操作。
您可以使用 sed 进行搜索,查找和替换,插入和删除字符串和行。它支持基本和扩展的正则表达式,使您可以匹配复杂的模式。
在本教程中,我们将讨论如何在 Linux 使用 sed 查找和替换字符串。我们还将向您展示如何执行递归搜索和替换。
sed 搜索并替换字符串
sed
有多个版本,它们之间在功能上有所不同。MacOS 使用 BSD 版本,并且大多数 Linux 发行版均默认预装 GNU sed。我们将使用 GNU 版本。
使用 sed 搜索和替换文本采用采用以下语法形式:
sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE
-i
选项指示sed
直接编辑文件。默认情况下,sed
将其输出写入到标准输出。如果提供扩展名(例如-i.bak),sed 会创建原始文件的备份。s
是替换命令,是 sed 最常用的命令。/
分隔符。它可以是任意字符,但通常使用斜杠/
作为分隔符。SEARCH_REGEX
要搜索的字符串或正则表达式。REPLACEMENT
使用此字符串进行替换。g
全局替换标志。默认情况下,sed
逐行读取文件,并且仅修改文件行中与搜索模式匹配第一次出现的字符。提供 g 替换标志后,所有匹配项都将被替换。INPUTFILE
要执行替换,删除,编辑等操作文件的名称。
sed 命令最佳实践是表达式周围加上引号,转义 Shell 元字符,避免 Shell 的解释 这里的表达式指的是 's/SEARCH_REGEX/REPLACEMENT/g'
。
让我们看一下如何在 Linux 使用 sed 命令搜索和替换文件中字符串或者文本。出于演示目的,我们将使用 file.txt 文件:
如果省略 g
标志,则仅替换每行与搜索模式匹配第一个字符串。sed -i 's/foo/linux/' file.txt 命令将会使用 linux 替换 foo:
sed -i 's/foo/linux/' file.txt
123 Foo linux foo
linux /bin/bash Ubuntu foobar 456
当使用全局替换标志 g, sed 替换所有与搜索模式匹配的字符串:
sed -i 's/foo/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456
您可能已经注意到,在前面的示例中,字符串 foobar
内的子字符串 foo
也被替换了。
如果这不是你想要的行为,请在搜索字符串的两端使用单词边界表达式 \b
。这样可以确保单词的部分不被匹配。
sed -i 's/\bfoo\b/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu foobar 456
要使搜索模式的匹配不区分大小写,请使用 sed 的 I
选项。在下面的示例中,我们同时使用 g
和 I
选项进行搜索替换:
sed -i 's/foo/linux/gI' file.txt
123 linux linux linux
linux /bin/bash Ubuntu linuxbar 456
如果你要搜索替换的字符串包含分隔符 /
,则需要使用反斜杠 \
来转义斜杠 /
。例如替换 /bin/bash
为 /usr/bin/zsh
,请运行以下命令:
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 个数字并将其替换为 number
,请运行以下命令:
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 编辑文件时,先进行备份是一个良好习惯。要备份原始文件,只需在 sed 命令的 -i
选项指定备份文件的后缀名即可。
例如,要编辑 file.txt
并备份原始文件名为 file.txt.bak
。请运行以下命令:
sed -i.bak 's/foo/linux/g' file.txt
如果要确保是否已创建原始文件的备份,请运行 ls
命令列出文件:
ls
file.txt file.txt.bak
递归查找和替换
有时您想在目录中进行递归搜索包含指定字符串的文件,并且使用指定的字符串替换所有文件。
可以通过 find 命令遍历目录的所有文件,然后通过 -exec 选项运行 sed 命令来完成对文件中字符串的搜索与替换。
以下命令将递归遍历当前工作目录的所有文件,并将文件名传递给 sed 将 bar 全局替换 为 foo。
find . -type f -exec sed -i 's/foo/bar/g' {} +
为避免文件名中包含空格的问题,请使用 find 命令 -print0
选项,该选项指示 find 命令后跟一个空字符打印文件名。
然后将 find 命令的标准输出通过管道传递给 xargs
命令。xargs 命令将会为 sed 命令提供最后一个参数文件名。
此处的 xargs
命令的 -0 选项是告诉 xargs 命令,传递给 xargs 命令的参数没有使用任何分隔符分隔参数,因为 find 使用了 -print0
选项。
因此最终的命令是 find . -type f -print0 | xargs -0 sed -i 's/foo/bar/g'。
find . -type f -print0 | xargs -0 sed -i 's/foo/bar/g'
要排除目录,请使用find 命令 -not -path 选项。例如,如果要替换本地 git 仓库以点 .
开头的文件,请运行以下命令:
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 搜索和替换文件中的文本非常简单。要了解 sed 命令,选项和标志的更多信息。
请访问 GNU sed手册 和 Grymoire sed 教程。如果您有任何问题或反馈,请随时发表评论。