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
的文本替换命令。find
、grep
和 xargs
命令都是解决问题的便捷方法。
感谢您花时间阅读文章!
收藏本站不迷路!
原文始发于微信公众号(滑翔的纸飞机):实用!Linux 递归搜索并替换文本的便捷方法
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/260831.html