代码之家  ›  专栏  ›  技术社区  ›  radman

Sed删除下划线并提升字符

  •  7
  • radman  · 技术社区  · 14 年前

    int some_var_name;
    

    新的是

    int someVarName_:
    


    查找包含的小写单词,将下划线替换为nothing,并将右边的字符升格为大写。在这之后,在比赛结束后加上一个。

    有没有可能用Sed和/或Awk和regex来实现这一点?如果不是为什么?

    任何例子脚本将不胜感激。

    非常感谢您的帮助。


    为了更清楚一点,重命名是针对一些使用错误命名约定编写的文件,这些文件需要与代码库的其余部分保持一致。不希望这样做是一个完美的替换,使所有内容都处于可编译状态。相反,脚本将运行,然后手动检查是否有任何异常。replace脚本纯粹是为了减轻手工修改所有内容的负担,我相信您会同意这是相当乏味的。

    3 回复  |  直到 14 年前
        1
  •  5
  •   Vineet    14 年前

    sed -re 's,[a-z]+(_[a-z]+)+,&_,g' -e 's,_([a-z]),\u\1,g'

    说明:

    这是一个sed命令,包含2个表达式(每个表达式在 -e s,,,g 是全球替代品。通常用斜杠代替逗号,但我认为在模式中使用反斜杠(没有逗号)更容易理解。后面的g(表示“global”)意味着将此替换应用于每行上的所有匹配项,而不仅仅是第一行。

    [a-z]+ (_[a-z]+)+ &_ ,在哪里 & 意思是“所有匹配的”,和 _ 只是一个字面下划线。总的来说,这个表达式的意思是在每个用下划线分隔的小写标记的末尾加一个下划线。

    第二个表达式与模式匹配 _([a-z])) 在这里 ( ) 是一个捕获组。这就意味着我们可以在以后引用它 \1 (因为它是第一个捕获群。如果有更多的话,他们会的 \2 , \3

    我们把它换成 \u\1 ,这是我们刚记住的字母,但用它来表示大写 \u

    这段代码没有做任何聪明的事情来避免咀嚼 #include 线条等;它将用大写字母替换下划线后面的小写字母的每个实例。

        2
  •  3
  •   Joseph Quinsey Taseen    14 年前

    几年前,我成功地将一个已有23年历史的遗留代码库转换为camelCase。只用了两天。但也有一些挥之不去的影响,花了几个月的时间来解决。它是一个 惹恼你的编码同事的好方法。

    我相信一个简单的,愚蠢的,sed式的方法是有好处的。据我所知,基于IDE的工具等不能:

    • 更改代码 通过ifdef编译
    • 更改注释中的代码

    主要 缺点

    大致分为五个阶段:

    1) Generate a list of tokens that you wish to change, and manually edit.
    2) For each token in that list, determine the new token.
    3) Apply these changes to your code base.
    4) Compile.
    5) Double-check via a manual diff, and do a final clean-up.
    

    对于步骤1,要生成要更改的令牌列表,请执行以下命令:

    cat *.[ch] | sed 's/\([_A-Za-z0-9][_A-Za-z0-9]*\)/\nzzz \1\n/g' | grep -w zzz | sed 's/^zzz //' | grep '_[a-z]' | sort -u > list1
    

    st_atime
    time_t
    ...
    

    在这个示例中,您确实不想更改这两个令牌,所以手动编辑列表以删除它们。但是你可能会错过一些,所以在这个例子中,假设你保留了这些。

    下一步2是生成一个脚本来执行更改。例如,命令:

    cat list1 | sed 's/\(.*\)/glob_sub "\\<\1\\>" xxxx_\1/;s/\(xxxx_.*\)_a/\1A/g;s/\(xxxx_.*\)_b/\1B/g;s/\(xxxx_.*\)_a/\1C/g;s/\(xxxx_.*\)_t/\1T/g' | sed 's/zzz //' > list2
    

    glob_sub "\<st_atime\>" xxxx_stAtime
    glob_sub "\<time_t\>" xxxx_timeT
    

    你只要把它扩展到d,e,f,…,x,y,z,

    我想您已经为您的开发环境编写了类似“glob\u sub”的东西了(如果没有,现在就放弃。)我的版本(csh,Cygwin)看起来像:

    #!/bin/csh
    foreach file (`grep -l "$1" */*.[ch] *.[ch]`)
      /bin/mv -f $file $file.bak
      /bin/sed "s/$1/$2/g" $file.bak > $file
    end
    

    (我的一些sed不支持--in-place选项,所以我必须使用mv。)

    source list2 .

    第四步是编译。编译器将(希望如此!)反对 xxxx_timeT . 事实上,它很可能会反对 timeT 但是额外的 xxx_ 增加保险。所以这一次你犯了个错误。用例如。

    glob_sub "\<xxxx_timeT\>" time_t
    

    第五步也是最后一步是使用您喜爱的diff实用程序手动检查您的更改,然后通过删除所有不需要的更改来进行清理 xxx号_ 前缀。为…而欢呼 "xxx_ 也有助于检查字符串中的令牌(实际上,添加一个xxx后缀可能是个好主意。)

        3
  •  3
  •   stinky472    14 年前

    考虑使用sed来搜索和替换这样的所有文本。如果没有C++标记器来识别标识符(具体地说是标识符,而不是标准库中的标识符,例如),那么你就是 拧紧 . pushBack被重命名为pushBack。映射::插入到映射::插入。地图到地图。基本字符串到基本字符串。printf到printf(如果您使用C库),等等。如果您不加区别地这样做,您将处于一个受伤的世界。

    我不知道有任何现有的工具可以自动将某个变量名重命名为someVarName,而不会出现上述问题。人们投票否决了这个帖子,可能是因为他们不明白我在这里的意思。我不是说塞德做不到, 我只是说它不会给你想要的

    如果能够识别哪些标记是标识符(特别是您的标识符),那么就有可能编写一个解析器来实现这一点(例如:使用sed),但我怀疑是否有一个工具专门用于您想做的事情,它可以在不需要手动润滑的情况下完成(尽管我可能是错的)。以这种方式对所有文本进行简单的搜索和替换本身就有问题。

    Check out the refactoring features of Visual Assist X .

    用VAX这种方式重构100个变量可能需要15分钟到半小时(如果使用热键,速度会更快),但它肯定比使用文本搜索和sed替换要好得多,就像另一个答案中描述的那样,并替换所有不应该被替换的代码。

    [主观]顺便说一句:如果你问我的话,下划线还是不属于驼色的。lowerCamelCase命名约定应使用lowerCamelCase。关于这一点有很多有趣的论文,但至少你的惯例是一致的。如果它是一致的,那么这是一个巨大的优势,而不是像fooBarèubaz这样的东西,一些愚蠢的程序员认为它能让事情更容易地对规则做出特殊的例外