摘要: 使用 Sed 完成文本替换操作任务是非常合适的。结合 find 命令,即可实现指定批量文件的文本替换。同时给出了Awk的解决方案作为对比。

问题

现在, 我要将一个原有Java项目中的一些包及下面的类移到另一个Java项目中复用(一个实际场景是,将自己工具箱的常用框架、工具包及类挪到具体项目中使用)。

Project javastudy:

Packages:

algorithm/ ,  foundations/,  javatech/, patterns/, threadprogramming/, datastructure/, javagui/, junitest3/, testdata/,  utils/

这些包下面会有很多子包。

现在要把这些包及其子包下面的所有 Java 文件移动到 Project ALLIN, 放在 package:  zzz.study 下面。

思路

在尝试使用 Eclipse 包重构无效之后, 我还是采用了最直观的方案: 将 Project javastudy 的上述包直接复制到 Project ALLIN 的包 zzz.study 下面。 复制之后, 要解决一个问题是: 必须手动更改每个 Java 文件的 package , import 引用。 比如 algorithm/BitsMapSort.java 中

package algorithm.sort;

import java.util.Arrays;
import datastructure.vector.NBitsVector;  

必须改成:

package zzz.study.algorithm.sort;

import java.util.Arrays;
import zzz.study.datastructure.vector.NBitsVector;

也就是说, 要将指定包的多个Java文件里的 package packageName 和 import packageName 批量替换成 package zzz.study.packageName ,  import zzz.study.packageName, 其中 packageName 取以下这些值: algorithm ,  foundations,  javatech, patterns, threadprogramming, datastructure, javagui, junitest3, testdata,  utils 。

Sed解决方案

难道真的要手动修改这么多文件的包和导入引用么?

于是想到了使用Sed. 注意到, 关键是匹配到 package|import packageName 即可。 可以使用分组和引用来完成。 命令如下:

sed -r -i 's/(package|import) (algorithm|foundations|javatech|patterns|threadprogramming|datastructure|javagui|junitest3|testdata|utils)(.*)/\1 zzz.study.\2\3/'

要批量完成多个文件的上述操作, 使用 find | xargs 即可:

find . -name "*.java" | xargs sed -r -i 's/(package|import) (algorithm|foundations|javatech|patterns|threadprogramming|datastructure|javagui|junitest3|testdata|utils)(.*)/\1 zzz.study.\2\3/'

Awk解决方案

显然,有了 find 命令,只要处理好单个文件的文本替换,然后使用 for 循环依次处理即可。 awk 处理单个文件的文本替换如下代码所示。 ARGV[1] 是传入的文件名,通常生成一个临时文件然后去覆写原来的文件,获得就地修改的效果。system 用来调用 shell 命令,挺好的特性。 ~ 用于匹配行是否满足某种条件。awk -f replace.awk BitsMapSort.java 用指定的 awk 程序 replace.awk 来处理指定文件 BitsMapSort.java。

$ cat replace.awk

$ awk -f replace.awk BitsMapSort.java

BEGIN {
origin_filename = ARGV[]
print origin_filename
filename = origin_filename".tmp"
}
{
if ($ ~ /^(package|import) (algorithm|foundations|javatech|patterns|threadprogramming|datastructure|javagui|junitest3|testdata|utils).*/) {
print $" zzz.study."$ >> filename
}
else {
print $ >> filename
} }
END {
cmd = "mv "filename" "origin_filename
system(cmd)
}

批量处理文件替换的命令是:

for file in $(find . -name '*.txt'); do awk -f replace.awk $file;  done

小结

本文分别使用Sed和Awk两个小工具来实现批量文件的文本替换。可以看到 Sed 由于具备就地修改的特性,比 Awk 实现要简洁的多。为什么还要使用Awk来实现呢? 一个重要原因是期望拥有多种解决途径和视角,不局限于单一方案。Awk 在规则的记录文件处理可以显示出更强大的威力,而Sed在任意文本内容替换上更具优势。

Sed 用法参考文章:

1.  Linux 之 Sed 用法

2.  Sed替换

3.  Sed命令的工作原理

4.  Sed&Awk 读书笔记之Sed

5.  sed高级用法:模式空间(pattern space)和保持空间(hold space)

使用Sed和Awk实现批量文件的文本替换的更多相关文章

  1. Linux 文本处理工具grep,sed,awk

    grep.sed和awk都是文本处理工具,虽然都是文本处理工具单却都有各自的优缺点,一种文本处理命令是不能被另一个完全替换的,否则也不会出现三个文本处理命令了.只不过,相比较而言,sed和awk功能更 ...

  2. shell之三大文本处理工具grep、sed及awk

    grep.sed和awk都是文本处理工具,虽然都是文本处理工具单却都有各自的优缺点,一种文本处理命令是不能被另一个完全替换的,否则也不会出现三个文本处理命令了.只不过,相比较而言,sed和awk功能更 ...

  3. shell编程基础(七): 处理文件命令sed与awk

    一.sed(以行为单位处理文件) sed意为流编辑器(Stream Editor),在Shell脚本和Makefile中作为过滤器使用非常普遍,也就是把前一个程序的输出引入sed的输入,经过一系列编辑 ...

  4. centos 正则,grep,egrep,流式编辑器 sed,awk -F 多个分隔符 通配符 特殊符号. * + ? 总结 问加星 cat -n nl 输出文件内容并加上行号 alias放~/.bash_profile 2015-4-10 第十三节课

    centos 正则,grep,egrep,流式编辑器 sed,awk -F 多个分隔符  通配符 特殊符号. * + ? 总结  问加星 cat -n  nl  输出文件内容并加上行号 alias放~ ...

  5. 【转帖】vim/sed/awk/grep等文件批处理总结

    vim/sed/awk/grep等文件批处理总结 https://www.cnblogs.com/cangqiongbingchen/p/9760544.html Vim相关操作 1.基础 * 和 # ...

  6. Linux文件处理三剑客(grep、sed、awk)

    下面所说的是Linux中最重要的三个命令在业界被称为"三剑客",它们是grep.sed.awk. 我们现在知道Linux下一切皆文件,对Linux的操作就是对文件的处理,那么怎么能 ...

  7. awk的批量replace功能

    awk的批量replace功能 需求 现在需要替换一个文本 文本内容如下 $cat file MD_D1TS_1_060_I MD_D1TS_1_061_F MD_D1TS_1_062_U MD_D1 ...

  8. 【Linux进阶】使用grep、find、sed以及awk进行文本操作

    目录 一.元字符 二.grep命令 1. 过滤出包含某字符串的行 2. 过滤出以某字符串开头(结尾)的行 3. 过滤出包含某字符串及其相邻的行 4. 过滤出不包含某关键字的行 5. 过滤出包含多个字符 ...

  9. Sed、Awk单行脚本快速参考

    文本间隔: # 在每一行后面增加一空行 sed G awk '{printf("%s\n\n",$0)}' # 将原来的所有空行删除并在每一行后面增加一空行. # 这样在输出的文本 ...

随机推荐

  1. ios 读取各种类型文件

    1.如何读取UTF-8编码的文本文件? 2.如何读取GB2312(中文)的文本文件? 3.如何读取其它编码文件? 首先解决第一个问题, 1.如何读取UTF-8编码的文本文件? NSString *fi ...

  2. tableView删除功能小记

    由于项目需要,做一个UITableView来实现删除功能. 效果如图: 功能思路其实不难: 交代一下,我自己要实现的效果: 1.TableView是分组的. 2.点击删除按钮后,某行被删除.   写完 ...

  3. php之常量

    前面的话 常量在javascript中并不存在,在php中却是与变量并列的重要内容.常量类似变量,但常量一旦被定义就无法更改或撤销定义.常量最主要的作用是可以避免重复定义,篡改变量值,提高代码可维护性 ...

  4. poj_1190 树状数组

    题目大意 给定一个S*S的矩形,该矩形由S*S个1x1的单元格构成,每个单元格内可以放一个整数,每次有如下可能操作: (1)改变某个单位单元格中的数的大小 (2)查询由若干个连续单元格构成的X*Y的大 ...

  5. 【APIO2016】Fireworks[DP 可并堆维护凸包优化]

    4585: [Apio2016]烟火表演 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 100  Solved: 66[Submit][Status] ...

  6. 使用HttpClient以文件流的方式上传文件(非multipartFormData方式)

    @Test public void testAdd() throws IOException { HttpPost post = new HttpPost("http://localhost ...

  7. {sharepoint} Setting List Item Permissions Programatically in sharepoint

    namespace Avinash { class Program { static void Main(string[] args) { SetListItemPermission(); } sta ...

  8. android极光推送

    版权声明:本文为博主原创文章,未经博主允许不得转载. Android开发记录18-集成推送服务的一点说明 关于推送服务,国内有很多选择,笔者也对它们进行了一个详细的对比,一般我们产品选择推送服务主要考 ...

  9. spring低版本报错:java.lang.IllegalStateException: Context namespace element ‘annotation-config’ and its parser class [*] are only available on

    参考来源:http://blog.csdn.net/sunxiaoyu94/article/details/50492083 使用spring低版本(2.5.6),使用jre 8发现错误: Unexp ...

  10. log4j配置输出到多个日志文件(转)

    參考资料:http://logging.apache.org/log4j/1.2/manual.html 通常我们项目里,有一些重要的日志想单独的输出到指定的文件,而不是全总输出到系统的日志文件中.那 ...