Contents

如何在文件中查找和替换文本

1. 简介

在本教程中,我们将了解如何利用内置 Linux 命令的强大功能快速轻松地搜索和替换字符串。每当我们需要更新大量文件中特定字符串的所有出现时,这是一种非常方便的技术。

例如,一个典型的场景可能是我们想要更新一组静态 HTML 文件中的版权声明。

2. 用sed搜索和替换

我们要查看的第一个命令是*sed *,它是一个强大的流编辑器,可用于对输入流执行基本转换。请查看我们的 Linux 中的流重定向指南,以重新了解流是什么。

使用sed,我们能够快速轻松地查找和替换文件中的一组字符。

让我们首先创建一个在我们的示例中使用的测试文件。我们将使用此处的文档 快速创建此测试文件:

$ cat <<-EOF > test.txt
This is a sample file created in 2019 to demonstrate character substitution. 
It will be used in 2019. 
Linux has a wide array of tools for us to use to achieve this.
2019 is a leap year.
EOF

让我们确认我们成功创建了测试文件:

$ cat test.txt
This is a sample file created in 2019 to demonstrate character substitution. 
It will be used in 2019. 
Linux has a wide array of tools for us to use to achieve this.
2019 is a leap year.

现在一切正常,所以让我们开始使用sed

2.1. 查找并替换第一次出现

我们将使用sed来查找和替换第一次出现的 term。在我们的例子中,我们会将年份更新为当前年份。让我们看看实现这一点的语法:

$ sed -i 's/{OLD_TERM}/{NEW_TERM}/' {file}

现在让我们将此命令应用于我们的示例:

$ sed -i 's/2019/2020/' test.txt

现在,我们打印文件的内容以确认我们只替换了第一次出现的“2019” :

$ cat test.txt
This is a sample file created in 2020 to demonstrate character substitution. 
It will be used in 2019. 
Linux has a wide array of tools for us to use to achieve this.
2019 is a leap year.

让我们分解我们的陈述,以更深入地了解其工作原理。首先,我们通过*-i选项来指示sed在我们的test.txt*文件中进行更改。默认情况下,sed将更改打印到终端。然后正则表达式指定我们要更改的内容:

  • 我们以字母**“s”**开始表达式,以便sed知道我们正在执行替换
  • 接下来,我们有字符串“2019”,它是OLD_TERM占位符的值。这是我们要替换的文本部分
  • 接下来是NEW_TERM占位符的值,即“2020”
  • 我们使用正斜杠*(/)分隔这些参数*

正如我们所见,sed是一种执行搜索和替换操作的快捷方式。

2.2. 查找并替换所有事件

默认情况下,sed仅替换它找到的第一个匹配项。我们可以轻松地覆盖此行为以替换文件中的所有实例。让我们看看我们可以用来实现这一点的表达式:

$ sed -i 's/{OLD_TERM}/{NEW_TERM}/g' {file}

我们在搜索表达式的末尾添加了“g”。这指示sed 全局替换所有出现

因此,让我们将其应用于我们的文本文件:

$ sed -i 's/2019/2020/g' test.txt

我们还可以在命令中添加更多文件,以全局替换多个文件中的所有匹配项:

$ sed -i 's/2019/2020/g' test.txt test2.txt test3.txt

现在让我们再次打印出*test.txt的内容。*这次我们将所有出现的“2019”替换为“2020”:

$ cat test.txt
This is a sample file created in 2020 to demonstrate character substitution.
It will be used in 2020.
Linux has a wide array of tools for us to use to achieve this.
2020 is a leap year.

2.3. 使用find查找和替换多个文件中的所有出现

Linux find 命令是基于 Unix 的系统中最重要和最常用的命令行实用程序之一。我们可以使用它根据我们指定的条件搜索和定位文件或目录的列表。让我们结合sedfind命令来搜索和替换多个文件中的匹配项。

$ find . -name *.txt -exec sed -i 's/2020/2070/g' {} \;

此语句在扩展名为 .txt 的所有文件中查找并替换所有“2020”到“2070”的实例 让我们分解一下这个说法:

  • 我们用 * . * 以当前工作目录为目标
  • -name参数允许我们将结果限制为与给定模式匹配的文件,在我们的例子中是 *.txt 获取所有文本文件
  • 我们使用*-exec* 结合find 找到匹配的文件后执行命令
  • 我们使用*{}* 来临时存储匹配的文件,以便使用sed命令执行
  • ;在我们的语句结束时标志着sed命令的结束

3. 用awk搜索和替换

在本节中,我们将看看*awk *。一种功能强大的脚本语言,专为文本处理而设计,通常用于数据提取和报告目的。与其他 Linux 实用程序一样,awk可以对流和文件执行操作。

awk有两个功能;subgsub我们可以用来执行替换。

subgsub在很大程度上是相同的,sub只会替换第一次出现的字符串。另一方面,gsub将替换所有出现。

让我们仔细看看如何使用awk 进行替换。

3.1. 使用awksub

让我们看看awk如何对我们的test.txt示例文件执行查找和替换操作:

$ awk '{sub(/{OLD_TERM}/,{NEW_TERM}); print}' {file}

在此语句中,我们调用awk并发送任务列表供awk执行。

让我们分解一下:

  • 我们列表中的第一个任务是替代任务,我们将其写为sub
  • Sub 指示awk查找所有出现的OLD_TERM并用**NEW_TERM替换它们
  • 我们的下一条指令指示awk将输出打印到标准输出流;控制台
  • 最后,我们有了awk将要处理的文件的名称

sed的一个显着区别是awk不会执行就地替换。意味着不会在文件中进行更新。

我们很快就会解决这个问题,但现在,让我们看看它的实际效果:

$ awk '{sub(/2019/,2020); print}' test.txt

我们得到的输出确认替换已正确执行:

This is a sample file created in 2020 to demonstrate character substitution.
It will be used in 2020.
Linux has a wide array of tools for us to use to achieve this.

正如预期的那样,awk已将“2019”的所有实例替换为“2020”。

但是,我们的输出被定向到控制台,而不是更新我们的原始文件。我们有一个技巧来解决这个问题。

我们将使用我们对流和流重定向的知识来更新我们的命令,以便将所做的更改保存到新的指定文件中:

$ awk '{sub(/2019/,2020); print . "text.txt" }' > test.txt

这次没有任何东西打印到控制台,但是让我们转储test.txt的内容来看看发生了什么:

$ cat test.txt
This is a sample file created in 2020 to demonstrate character substitution.
It will be used in 2020.
Linux has a wide array of tools for us to use to achieve this.

在这里,我们可以看到awk命令的输出被正确地重定向到我们的输入文件,从而为我们更新了它。

3.2. 使用awkgsub

让我们看一下语法:

$ awk '{gsub(/{OLD_TERM}/,{NEW_TERM}); print}' {file}

** gsub代表全局替换。因此,我们可以使用它用给定的字符串替换所有出现的字符串或正则表达式**。让我们看看awk如何使用gsub命令对我们的示例文件执行查找和替换操作

$ awk '{gsub(/i/,"a"); print}' test.txt

这是我们的结果输出:

Thas as a sample fale created an 2020 to demonstrate character substatutaon. 
It wall be used an 2020. 
Lanux has a wade array of tools for us to use to achaeve thas.

正如预期的那样, gsub将所有“i”实例替换为“a”。

然而,这只会在我们的终端上打印结果,为了保存更改,我们可以像这样修改我们的命令:

$ awk '{gsub(/i/,"a"); print}' test.txt > test2.txt

我们命令末尾的修改指示awk创建一个名为 test2.txt 的新文件并将更改保存到其中。