Shell在代码重构中的应用了解下

437 阅读3分钟


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

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

方法一,使用Sed:

1shell> find /path -name "*.php" -print0 | xargs -0 sed '
2           s/foo_bar/fooBar/g
3       '

方法二,使用AWK:

1shell> find /path -name "*.php" -print0 | xargs -0 awk '
2           {
3               gsub(/foo_bar/, "fooBar")
4               print
5           }
6       '

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

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

重构前的代码示例:

 101 <?php
 202 includeClass('...');
 303 echo 'a';
 404
 505 echo 'b';
 606 includeClass('...');
 707 includeClass('...');
 808
 909
1010 echo 'c';
1111
1212 echo 'd';
1313 includeClass('...');
1414
1515
1616 echo 'e';
1717 ?>

重构后的代码示例:

 101 <?php
 202 echo 'a';
 303
 404 echo 'b';
 505
 606 echo 'c';
 707
 808 echo 'd';
 909
1010 echo 'e';
1111 ?>

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

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

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


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

 1#!/bin/bash
 2
 3for PHP in $@; do
 4    /bin/sed -i '
 5        /includeClass/I {
 6            h
 7            d
 8        }
 9
10        /^$/ {
11            x
12            /includeClass/Id
13            x
14        }
15
16        h
17    ' $PHP
18done

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

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

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

 1#!/bin/bash
 2
 3for PHP in $@; do
 4    TMP=$(mktemp)
 5
 6    /bin/awk '
 7        BEGIN {
 8            IGNORECASE = 1
 9        }
10
11        /includeClass/ {
12            previous = $0
13            next
14        }
15
16        /^$/ {
17            if (previous ~ /includeClass/) {
18                previous = $0
19                next
20            }
21        }
22
23        {
24            previous = $0
25            print
26        }
27    ' $PHP > $TMP
28
29    /bin/cp -f $TMP $PHP
30    /bin/rm -f $TMP
31done

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

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

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

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

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

简单的任务用Sed写很合适,复杂的任务则最好用AWK写,具体可以参考Sed One Line和AWK One Line等。


很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的加群(点击→)此处我的官方群