Contents
  1. 1. 解题思路
  2. 2. 源代码

为什么会有这个需求?
呃,不知道众程序猿们有没有听过这么一个笑话,大意说从前有个很努力的程序员,每天不断地优化服务器上的代码,但是因为工作量看起来没有那么大,而被不懂代码的上司认为工作不积极,于是该程序员直接把所有注释全部删除,然后离职了。。。

我就是膜拜一下这个前辈,然后就顺便想研究下如果全部删除注释,该怎么借助脚本实现。作为码农,一定不能勤奋了,原本可能花2个小时手动删除就能完事的任务一定要花一整天去研究怎么来写这个脚本达到批量删除的目的。

这段代码就是这样来的。。。

解题思路

一般来说,我们使用到最多的添加注释的方法无非就两个:

  • /* 我是注释 */
  • // 我也是注释

那我们的思路也很简单暴力,就是从原文件中一个字符一个字符地读取,正常的情况就再把字符一个一个地输出到另一个文件中;然后碰到 /* 之后,所有的字符不再输出,直到遇到后面的 */ 符号。
同理处理// 符号。

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

# 删除程序中的/**/和//所包含的注释内容

import os
import re
import io

# 根目录,在你的脚本中,记得更改这个目录
top_dir = "/Users/Desktop/test"

# 标识状态
S_INIT = 0
S_SLASH = 1
S_BLOCK_COMMENT = 2
S_BLOCK_COMMENT_DOT = 3
S_LINE_COMMENT = 4
S_STR = 5
S_STR_ESCAPE = 6

# 处理文件夹
def trim_dir(path):
print("dir:" + path)
for root, dirs, files in os.walk(path):
print("***")
print(files)
for name in files:
trim_file(os.path.join(root,name))

# 处理文件
def trim_file(path):
print("file:" + path)
if re.match(r".*?\.(java|c|h|m)$",path):
print("process!")
else:
print("ignore")
return

bak_file = path + ".bak"
try:
os.rename(path,bak_file)
except:
print("bak exception -->" + bak_file)

fp_src = open(bak_file)
fp_dst = open(path,'w')
cnt = 0

for line in fp_src.readlines():
print("--> 当前是第%d行" %cnt)
print(line)
cnt += 1
state = S_INIT

if cnt < 7:
fp_dst.write(line)
continue

for c in line:
# State INIT
if state == S_INIT:
if c == '/':
state = S_SLASH
elif c == '"':
state = S_STR
fp_dst.write(c)
else:
fp_dst.write(c)
# State slash:
elif state == S_SLASH:
if c == '*':
state = S_BLOCK_COMMENT
elif c == '/':
state = S_LINE_COMMENT
else:
fp_dst.write('/')
fp_dst.write(c)
state = S_INIT
# State Block_comment start /
elif state == S_BLOCK_COMMENT:
if c == '*':
state = S_BLOCK_COMMENT_DOT
# State Blcok_comment state *
elif state == S_BLOCK_COMMENT_DOT:
if c == '/':
state = S_INIT
elif c == '*':
state = S_BLOCK_COMMENT_DOT #再次碰到*还得持续DOT状态,不然会出错
else:
state = S_BLOCK_COMMENT

# state line comment
elif state == S_LINE_COMMENT:
if c == '\n':
state = S_INIT
fp_dst.write(c)
# state str
elif state == S_STR:
if c =='\\':
state = S_STR_ESCAPE
elif c == '"':
state = S_INIT
fp_dst.write(c)
# state str_escape
elif state == S_STR_ESCAPE:
state = S_STR
fp_dst.write(c)

fp_src.close()
os.remove(bak_file)
fp_dst.close()

trim_dir(top_dir)

有了之前的解题思路,再加上代码中少量的注释,其实我们已经能够比较清晰地了解程序的处理逻辑了,只不过我们借助了标志位,来决定是否复制原文件中的字符。
没什么技术难度。就是记得要更改下你要修改的文件夹的目录。

还有一点:
这段代码似乎有点小bug,就是如果碰到不规则的段落注释符可能会出问题。

一定要备份一下你的原文件!
一定要备份一下你的原文件!
一定要备份一下你的原文件!

别怪我重要的事情没有说3遍。如果有问题了,就自己改下脚本的逻辑,每个人的注释习惯不一样。

Contents
  1. 1. 解题思路
  2. 2. 源代码