我需要一个sed脚本来自动将C函数转换为较低的蛇案例。
到目前为止,我所提供的内容如下所示,将带有下划线的骆驼案例单词分开,但它并不会降低它们的含量,它会影响所有内容。
sed -i -e 's/\([a-z0-9]\)\([A-Z]\)/\1_\L\2/g' `find source/ -type f`
如何使其仅适用于功能?即仅限字符串后跟字符'('。
另外,我需要做什么才能让字符串变成小写?
例如,如果我有这段代码:
void destroyPoolLender(PoolLender *lender)
{
while (!isListEmpty(&lender->pools)) {
MemoryPool *myPool = listPop(&this->pool);
if (pool->inUse) {
logError("%s memory pool still in use. Pool not released.", pool->lenderName);
} else {
free(pool);
}
}
listDestroy(&this->pool);
}
一旦转换它应该看起来像这样:
void destroy_pool_lender(PoolLender *lender)
{
while (!is_list_empty(&lender->pools)) {
MemoryPool *myPool = list_pop(&this->pool);
if (pool->inUse) {
log_error("%s memory pool still in use. Pool not released.", pool->lenderName);
} else {
free(pool);
}
}
list_destroy(&lender->pools);
}
注意myPool是如何不受影响的,因为它不是函数名。
答案 0 :(得分:1)
我们可以用sed做到这一点。诀窍是将所有内容(包括(
)作为捕获组2进行匹配,并使用\l
而不是\L
来仅限下第一个匹配的字符:
s/\([a-z0-9]\)\([A-Z][A-Za-z0-9]*(\)/\1_\l\2/
我们不能只使用/g
修饰符,因为后续替换可能会重叠,因此请在循环中使用它:
#!/bin/sed -rf
:loop
s/([a-z0-9])([A-Z][A-Za-z0-9]*\()/\1_\l\2/
tloop
(我使用-r
代替GNU sed来减少我需要的反斜杠数。)
进一步的简化是匹配非字边界;这消除了对两个捕获组的需求:
#!/bin/sed -rf
:loop
s/\B[A-Z]\w*\(/_\l&/
tloop
$ sed -r ':loop;s/\B[A-Z]\w*\(/_\l&/;tloop' \
<<<'SomeType *myFoo = callMyFunction(myBar, someOtherFunction());'
SomeType *myFoo = call_my_function(myBar, some_other_function());
请注意,这只会修改函数调用和定义 - 如果您正在存储或传递函数指针,则很难识别哪些名称是函数。如果您只有70k行要处理,您可以选择手动修复它们(对编译错误做出反应)。如果你正在使用1M +,你可能需要一个合适的重构工具。
答案 1 :(得分:1)
bash的解决方案。它使用nm
命令从目标文件中获取信息。请参阅man nm
。
要从您需要的源创建目标文件,并为每个源文件运行gcc
-c
选项(可能是您已经拥有它们,由make
命令创建。然后,你可以跳过这一步):
gcc -c one.c -o one.o
gcc -c two.c -o two.o
用法: ./convert.sh one.o two.o
#!/bin/bash
# store original function names to the variable.
orig_func_names=$(
# get list symbols from all object files
nm -f sysv "$@" |
# picks the functions and removes all information except names.
sed -n '/FUNC/s/\s.*//p' |
# selects only functions, which contain the uppercase letter in the name.
sed -n '/[A-Z]/p'
);
# convert camel case names to snake case names and store new names to the variable.
new_func_names=$(sed 's/[A-Z]/_\l&/g' <<< "$orig_func_names")
# create file, containing substitute commands for 'sed'.
# Example of commands from this file:
# s/\boneTwo\b/one_two/g
# s/\boneTwoThree\b/one_two_three/g
# etc. One line to the each function name.
paste -d'/' <(printf 's/\\b%s\\b\n' ${orig_func_names}) <(printf '%s/g\n' ${new_func_names}) > command_file.txt
# do converting
# change object file extenstions '.o' to C source - '.c' file extensions.
# were this filenames: one.o two.o three.o
# now they are: one.c two.c three.c
# this 'sed' command creates backup for the each file and change the source files.
sed -i_backup -f command_file.txt "${@/.o/.c}"
应注意,在此解决方案中,执行时间呈指数级增长。 例如,如果我们有70000行和1000个函数,那么它需要进行7000万次检查(70 000行* 1000个函数)。知道它需要花多少时间会很有趣。
<强>输入强>
档案one.c
#include <stdio.h>
int one();
int oneTwo();
int oneTwoThree();
int oneTwoThreeFour();
int one() {
puts("");
return 0;
}
int oneTwo() {
printf("%s", "hello");
one();
return 0;
}
int oneTwoThree() {
oneTwo();
return 0;
}
int oneTwoThreeFour() {
oneTwoThree();
return 0;
}
int main() {
return 0;
}
档案two.c
#include <stdio.h>
int two() {
return 0;
}
int twoThree() {
two();
return 0;
}
int twoThreeFour() {
twoThree();
return 0;
}
<强>输出强>
档案one.c
#include <stdio.h>
int one();
int one_two();
int one_two_three();
int one_two_three_four();
int one() {
puts("");
return 0;
}
int one_two() {
printf("%s", "hello");
one();
return 0;
}
int one_two_three() {
one_two();
return 0;
}
int one_two_three_four() {
one_two_three();
return 0;
}
int main() {
return 0;
}
档案two.c
#include <stdio.h>
int two() {
return 0;
}
int two_three() {
two();
return 0;
}
int two_three_four() {
two_three();
return 0;
}