IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

说说Shell在代码重构中的应用

火丁笔记 2011-03-21 00:09:20 累计浏览 4,019 次
本机暂存

代码重构(Code refactoring)有时是很枯燥的,字符串替换之类的操作不仅乏味,而且还容易出错,好在有一些工具可用,以PHP为例,如:RephactorScisr等等,不过现成的工具往往意味着不够灵活,所以今天我要说说Shell在代码重构中的应用。

先来个简单的,假设我们要把PHP文件中的foo_bar全都替换成fooBar,那么可以如下:

方法一,使用Sed:

shell> find /path -name "*.php" | xargs sed 's/foo_bar/fooBar/g'

方法二,使用AWK:

shell> find /path -name "*.php" | xargs awk '{ gsub(/foo_bar/, "fooBar"); print; }'

注:为了简单,我把结果直接打印到终端屏幕了,至于如何保存,稍后会说明。

接着说个复杂的:假设某个PHP项目,以前使用类之前必须调用一个名为“includeClass”的方法,现在改用类自动加载的方式,所以要删除硬编码的includeClass调用,出于美观的考虑,如果includeClass下面一行是空行的话,也一起删除,同时考虑大小写不敏感的因素。

重构前的代码示例:

01 <?php
02 includeClass('...');
03 echo 'a';
04
05 echo 'b';
06 includeClass('...');
07 includeClass('...');
08
09
10 echo 'c';
11
12 echo 'd';
13 includeClass('...');
14
15
16 echo 'e';
17 ?>

重构后的代码示例:

01 <?php
02 echo 'a';
03
04 echo 'b';
05
06 echo 'c';
07
08 echo 'd';
09
10 echo 'e';
11 ?>

在动手前,我们需要先摸摸底,了解一下大概的情况:

shell> grep -I -ri includeClass /path | more

其中,grep命令的参数乍一看不好记,不过只要按照我说的方法记,就永远不会忘:前面的参数看做英文,后面的参数看做拼音 :) 。至于参数的具体含义,请参阅man文档

方法一,使用Sed编写脚本script.sh:

#!/bin/sh

for PHP in $@; do
    /bin/sed -i '
        /includeClass/I {
            h
            d
        }

        /^$/ {
            x
            /includeClass/Id
            x
        }

        h
    ' $PHP
done

注:篇幅所限,我把正则写的比较简单

Sed的缺点是代码可读性比较差,优点是代码较短。另外内置的“-i”选项可以直接完成保存,这是我喜欢Sed的原因之一。

方法二,使用AWK编写脚本script.sh:

#!/bin/sh

for PHP in $@; do
    TMP=$(mktemp)

    /bin/awk '
        BEGIN {
            IGNORECASE = 1
        }

        /includeClass/ {
            previous = $0
            next
        }

        /^$/ {
            if (previous ~ /includeClass/) {
                previous = $0
                next
            }
        }

        {
            previous = $0
            print
        }
    ' $PHP > $TMP

    /bin/cp -f $TMP $PHP
    /bin/rm -f $TMP
done

注:篇幅所限,我把正则写的比较简单

AWK的缺点是代码比较长,优点是代码可读性较好。另外程序中是通过生成一个唯一的临时文件来完成保存的。

提醒:直接覆盖原始文件有时候并不合适,毕竟可能有没考虑周详的地方,使用SVN的话就不会有这样的顾虑了,因为即便覆盖了原始文件,也可以在提交前通过“svn diff”命令来检查对错,就算是提交了,也可以恢复到以前的版本。

如果调用script.sh脚本呢?这里给个最一般的例子:

shell> find /path -name "*.php" | xargs /path/to/script.sh

简单的任务用Sed写很合适,复杂的任务则最好用AWK写,实战是学习的最好方法,具体可以参考Sed One LineAWK One Line等资料。

说明:本文用到的Sed和AWK均指GNU版本。

同分类推荐文章

  1. 从零重建 macOS 开发机:可复现的环境初始化流程 (2026-06-14 20:36:00)
  2. 百度物理网络监控工具开源第二弹:毫秒级监控工具 baize,让你的网络问题无处遁形 (2026-06-11 08:10:28)
  3. How to Set Up Homebrew Tap for Private CLI Tools: A Complete Guide (2026-05-27 02:13:03)

查看更多 DevOps 文章 →

建议继续学习

  1. 使用gettext来支持PHP的多语言 (累计阅读 39,268)
  2. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,164)
  3. Bash的模式和配置文件加载 (累计阅读 24,407)
  4. Paypal接口详细代码(PHP版,非API接口) (累计阅读 19,408)
  5. WEB系统需要关注的一些点 (累计阅读 18,218)
  6. 28个Unix/Linux的命令行神器 (累计阅读 16,790)
  7. 批量添加主机到cacti+nagios的监控报警系统中 (累计阅读 14,990)
  8. 我常用的主机监控shell脚本 (累计阅读 13,429)
  9. 我的PHP,Python和Ruby之路 (累计阅读 13,146)
  10. include(“./file.php”)和include(“file.php”)区别 (累计阅读 12,789)