使用 bash 使用正则表达式重新格式化文件列表中的“#include”

使用 bash 使用正则表达式重新格式化文件列表中的“#include”

考虑以下对代码文件进行简单循环的代码:

#!/bin/bash
dir="."
find $dir -name *.cpp -o -name *.h | while read file; do
    echo "processing: "$file
    # Process file here
done

每个文件都以这样的凌乱包含开头

#include<iostream>
#include <vector>
#include"this_is_file1.h"
#include "this_is_file2.h"
#include "This_Is_File3.h"
#include"thisIsFile4.h"
#include "ThisIsFile5.h"
#include"dir/thisIsFile6.h"
#include "dir/ThisIsFile7.h"
#include "dir/ThisIsFile8.txx"
#include "dir/ThisIsFILe9.txx"

我想像这样进行转换(并覆盖旧文件)

#include <iostream>
#include <vector>
#include "this_is_file1.h"
#include "this_is_file2.h"
#include "this_is_file3.h"
#include "this_is_file4.h"
#include "this_is_file5.h"
#include "this_is_file6.h"
#include "this_is_file7.h"
#include "this_is_file8.txx"
#include "this_is_file9.txx"

更正式地说:

  • 包含和文件名之间应该正好有一个空格
  • 不应该有任何大写字母,并且每个已替换的连续大写字母序列前面都应该有一个下划线,除非它是文件名的开头
  • 不应该有任何目录名

如何用 bash 做到这一点?

答案1

以下 sed 脚本应该执行此操作:

s/\(#include\) *\([^ ]\+\)/\1 \2/

/^#include "/ {
    s/".*\//"/
    s/"\(.\)/"\l\1/g
    s/\([^A-Z]\)\([A-Z]\)/\1_\l\2/g
    s/_\+/_/g
}

可以通过运行以下命令将其应用于文件:

sed -i.bak -f fix.sed input...

(这假设上面的脚本被调用fix.sed,并且之后可以给出任意数量的文件作为参数。.bak如果您不想创建任何备份,请删除。)

第一个 sed 替换表达式匹配#include后跟可能为空的空格 ( \ *),并用单个空格替换该运行。它还将行 ( [^ ]\+) 的其余部分转换为小写(使用\l)。

接下来的四个 sed 表达式(所有这些表达式仅适用于以 开头的行#include ")执行以下操作:

  1. 去除路径名(直到并包括最后一个斜杠的所有内容);

  2. 将引号之间的第一个字符转为小写;

  3. 在每组大写字母的开头插入下划线并将该组的第一个字符转换为小写;

  4. 挤压运行可能由前面的步骤插入的下划线。

这是不完美的,但确实按预期翻译了您的示例输入。

答案2

您可能会发现使用诸如阿风格整齐地格式化您的代码,并且不仅仅修复#include行。

您的代码按原样没有问题,但如果您的文件名中没有空格或其他奇怪的地方,您也可以使用find

astyle --style=allman -A1 --indent=spaces=4  \
   --break-blocks --pad-oper --pad-header --unpad-paren \
   --max-code-length=200 \
   $(find . -name '*.cpp' -print) $(find . -name '*.h' -print)

答案3

perl -i.bak -pe '
   if( s!(#include) *(["<])(.*/)?!$1 $2!){  ## if is a include line
        s/(?<=[a-z])(?=[A-Z])/_/g;          ##   insert CamelCase "_"
        tr/A-Z/a-z/ }'   file               ##   lowercase ids

相关内容