递归遍历目录并替换函数调用

1 投票
2 回答
516 浏览
提问于 2025-04-17 00:57

我想要递归地遍历一个文件夹,找到所有至少包含以下函数调用之一的文件:

A(a)
B(a,b)
C(a,b,c)

现在,忽略参数的话,我可以用下面的方式得到这样的文件列表:

grep -r -l '[A-C](' .

虽然我相信我也可以以某种方式匹配这些参数。在找到的文件中,我想做以下几件事:首先,我想备份一下,也就是说,把原文件保存为filename.ext_bak或者其他类似的名字,而在filename.ext文件中,我想把每一个函数调用替换成:

X(a,...) 

替换成

#ifdef LOL
   X_new(f(a),...)
#else
   X(a,...)
#endif

其中X可以是A、B、C,并且注意X_new中的每个参数都被包裹在一个函数f(...)里。希望能得到一些帮助!提前谢谢!

2 个回答

1
find -type f -exec perl -i.bak -pe'
   if (my ($orig, $pre, $func, $args, $post) =
       /^((.*)\b(A|B|C)\((.*?)\)(.*?))\n/s
   ) {
       $args = join ', ', map { "f($_)" } split /,\s*/, $args;
       $_ = "#ifdef LOL\n";
       $_ .= $pre${func}_new($args)$post\n";
       $_ .= "#else\n";
       $_ .= $orig\n";
       $_ .= "#endif\n";
   }
' {} +

这个代码做了很多假设。如果其中某个假设带来了太多问题,请告诉我。

1

这个代码使用了 os.walk,可以递归地遍历所有文件,也就是说它会从当前工作目录开始,一个一个地找到所有文件。

参数 backup='_bak' 是告诉 fileinput.input 要为每个文件做一个备份。

import os
import sys
import re
import fileinput

def sub_callback(match):
    func,args=match.groups()
    fargs=','.join('f({a})'.format(a=a) for a in args.split(','))
    return ('''\
#if def LOL
    {func}_new({fa})        
#else
    {func}({a})
#endif
'''.format(func=func,a=args,fa=fargs))

for root, dirs, files in os.walk('.'):
    for line in fileinput.input(
        (os.path.join(root,name) for name in files),
        inplace=True,
        backup='_bak'
        ):
        line=re.sub(r'\b([A-C])\((.*?)\)',sub_callback,line)
        sys.stdout.write(line)

撰写回答