实用!Linux 递归搜索并替换文本的便捷方法

1. 写在前面

Linux 环境下工作时,在文件中搜索并将其替换为新文本是典型的操作,例如,想搜索和替换给定目录下的所有文本文件,包括其子目录下的文本文件。

本文,将通过示例介绍如何递归搜索和替换文本文件。

2. 示例文本结构

在详细介绍方案之前,先创建一个名为 mydir 的示例目录,并在其下创建一些子目录和文件(可以多拷贝几份用于不同命令示例):

root@jpzhang-dev:~/linux# tree ./mydir/
--------------------------------------------------------------------------------------
./mydir/
├── dir1
│   ├── dir1.1
│   │   ├── dir1.1.1
│   │   │   └── text1.1.1.txt
│   │   └── text1.1.txt
│   └── text1.txt
└── parent.txt

3 directories, 4 files

文本文件内容:

root@jpzhang-dev:~/linux# head $(find mydir -name "*.txt")
--------------------------------------------------------------------------------------
==> mydir/parent.txt <==
I like Linux.

==> mydir/dir1/text1.txt <==
I like Linux.

==> mydir/dir1/dir1.1/text1.1.txt <==
I like Linux.

==> mydir/dir1/dir1.1/dir1.1.1/text1.1.1.txt <==
I like Linux.

接下来介绍:搜索 mydir 目录下的所有文本文件,并将 Linux 替换为 Linux operating system

3. 解决思路

当前面临的并不是真正的算法问题。不过,可以借用 “分而治之” 的思想来解决这个问题。可以把问题分成两个子问题:

(1)在单个文件中将 Linux 替换为 Linux operating system;

(2)查找指定目录 mydir 下的所有文本文件;

本文将分别求解这两个子问题,然后将它们合并起来,求解原始问题。


4. 在单个文本文件中搜索和替换

首先,解决问题:在一个文件中,将 Linux 替换为 Linux operating system。在 Linux 命令中,可以通过多种方式进行文本替换并将结果保存回文件中。解决这个问题,可选择使用 sed 命令来执行搜索和替换工作。

示例:将 parent.txt 文件中的 Linux 替换为 Linux operating system

root@jpzhang-dev:~/linux/mydir# sed -i 's/Linux/& operating system/g' parent.txt 
root@jpzhang-dev:~/linux/mydir# cat parent.txt
--------------------------------------------------------------------------------------
I like Linux operating system.

接下来,我们搜索 mydir 目录下所有文本文件,将找到的文件交给 sed 命令来替换文本。

5. 递归搜索和替换

有很多方法可以找到指定目录下所有文本文件,并通过执行 sed 命令进行替换。

在本节中,我们将介绍四种不同的方法。

5.1 使用 find 命令和 -exec {}+ 参数

find 命令可以递归查找指定目录下的文件。此外,它还提供了一个选项 -exec <command> {}+ 选项,对所有找到的文件执行命令。

命令:

find mydir -name '*.txt' -exec sed -i 's/Linux/& operating system/g' {} +

示例:

root@jpzhang-dev:~/linux# find mydir -name '*.txt' -exec sed -i 's/Linux/& operating system/g' {} +

root@jpzhang-dev:~/linux# head $(find mydir -name "*.txt")
--------------------------------------------------------------------------------------
==> mydir/parent.txt <==
I like Linux operating system.

==> mydir/dir1/text1.txt <==
I like Linux operating system.

==> mydir/dir1/dir1.1/text1.1.txt <==
I like Linux operating system.

==> mydir/dir1/dir1.1/dir1.1.1/text1.1.1.txt <==
I like Linux operating system.

在上述命令中,{}是一个占位符,用来接收 find 命令搜索到的所有文件列表,因此,sed 命令执行如下所示:

sed -i '..code..' foundFile1 foundFile2 foundFile3...foundFileN

实际,只需要调用一次 sed 命令,而不是 n 次。

5.2 使用 find 命令和 xargs 命令

xargs 命令可以读取 find 命令的输出,即找到的文件列表,然后将它们构建到另一个命令的参数中。

命令:

find mydir -name '*.txt' | xargs sed -i 's/Linux/& operating system/g'

示例:

root@jpzhang-dev:~/linux# find mydir -name '*.txt' | xargs sed -i 's/Linux/& operating system/g'

root@jpzhang-dev:~/linux# head $(find mydir -name "*.txt")
--------------------------------------------------------------------------------------
==> mydir/parent.txt <==
I like Linux operating system.

==> mydir/dir1/text1.txt <==
I like Linux operating system.

==> mydir/dir1/dir1.1/text1.1.txt <==
I like Linux operating system.

==> mydir/dir1/dir1.1/dir1.1.1/text1.1.1.txt <==
I like Linux operating system.

5.3 使用 grep 命令和 xargs 命令

grep 命令通过 -Rl 选项可进行文件搜索,达到 find 命令能力;

-R 选项告诉 grep 递归搜索目录,而 -l 选项跳过匹配内容,告诉 grep 只显示匹配文件的文件名。

使用 grep 命令搜索包含 Linux 的所有文件:

root@jpzhang-dev:~/linux# grep -Rl 'Linux' mydir
--------------------------------------------------------------------------------------
mydir/parent.txt
mydir/dir1/text1.txt
mydir/dir1/dir1.1/text1.1.txt
mydir/dir1/dir1.1/dir1.1.1/text1.1.1.txt

接下去,只需要将输出结果导入 xargs 命令即可;

命令:

grep -Rl 'Linux' mydir | xargs sed -i 's/Linux/& operating system/g'

示例:

root@jpzhang-dev:~/linux# grep -Rl 'Linux' mydir | xargs sed -i 's/Linux/& operating system/g'

root@jpzhang-dev:~/linux# head $(find mydir -name "*.txt")
--------------------------------------------------------------------------------------
==> mydir/parent.txt <==
I like Linux operating system.

==> mydir/dir1/text1.txt <==
I like Linux operating system.

==> mydir/dir1/dir1.1/text1.1.txt <==
I like Linux operating system.

==> mydir/dir1/dir1.1/dir1.1.1/text1.1.1.txt <==
I like Linux operating system.

5.4 使用 Zsh

Zsh 属于 Shell 的一种,和 Bash 一样,但比 Bash 更好用,Zsh 完全兼容 Bash,拥有极其丰富的插件,其强大的自动补全参数、文件名以及自定义功能,可以大大提高我们使用 Linux 的效率。

Ubuntu 安装:

sudo apt install zsh

进入 zsh 模式:

zsh

搜索文件:

(zsh)# ls -1 mydir/**/*.txt
--------------------------------------------------------------------------------------
mydir/dir1/dir1.1/dir1.1.1/text1.1.1.txt
mydir/dir1/dir1.1/text1.1.txt
mydir/dir1/text1.txt
mydir/parent.txt

因此,使用 Zsh 可以更简单地解决问题:

jpzhang-dev# sed -i 's/Linux/& operating system/g' mydir/**/*.txt
jpzhang-dev# head mydir/**/*.txt
--------------------------------------------------------------------------------------
==> mydir/dir1/dir1.1/dir1.1.1/text1.1.1.txt <==
I like Linux operating system.

==> mydir/dir1/dir1.1/text1.1.txt <==
I like Linux operating system.

==> mydir/dir1/text1.txt <==
I like Linux operating system.

==> mydir/parent.txt <==
I like Linux operating system.

仅 sed 命令就能解决问题。

6.结论

在本文中,我们讨论了在给定目录下进行递归搜索和替换的四种不同方法。其基本思想是首先找到所有文本文件,然后将文件列表传递给类似 sed 的文本替换命令。findgrep 和 xargs 命令都是解决问题的便捷方法。

感谢您花时间阅读文章!

收藏本站不迷路!


原文始发于微信公众号(滑翔的纸飞机):实用!Linux 递归搜索并替换文本的便捷方法

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/260831.html

(0)
土豆大侠的头像土豆大侠

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!