更改 #include 文件名以匹配大小写

Changing #include filenames to match case

本文关键字:大小写 #include 文件名 更改      更新时间:2023-10-16

我有一个 C/C++ 源代码的主体,其中 #include 语句中的文件名与 *.h 文件不完全匹配。匹配正确,但不区分大小写。这是 Windows 系统中出现的源文件类型。

我想更改所有源文件,以便所有#include语句都与它们引用的文件名完全匹配。

所有要更改的文件名都括在引号中。

例:

文件列表

File1.h
FILE2.H
file1.cpp

文件1.cpp

#include "file1.h"
#include "file2.h"

将文件 1.cpp 更改为

#include "File1.h"
#include "FILE2.H"

我想创建一个自动脚本来执行此更新。

我在下面列出了这个过程的各个部分的步骤,但我似乎无法将这些部分组合在一起。

  1. 创建所有 *.h 文件的列表,ls *.h > include.lst.这将创建一个大小写正确的所有文件名的文件。
  2. 使用include.lst中的文件名创建一个 sed 命令's/<filename>/<filename>/I'该命令执行不区分大小写的搜索,并将匹配项替换为大小写正确的文件名。我相信我只需要进行一次替换,但添加全局 g 将处理多次出现。
  3. 将此替换列表应用于目录中的所有文件。

我想了解如何创建 sed 命令的建议 2) 给定include.lst.我想我可以处理其余的。

  1. 在脚本中使用sed,或使用 Perl 脚本:

    find . -name *.c -print0 | xargs -0 sed -i.bak -e "s/#includes"([^"]+/)"/#includes"L1"/"
    

    -i.bak会将文件备份到original_file_name.bak因此您无需担心搞砸了

    此行将 C 文件中的所有标头包含更改为小写。

  2. 然后,您要更改所有文件名:

    find . -name *.h -print0 | xargs -0 rename 's/(*)/L1/'
    

    这会将所有头文件重命名为小写。

这仅适用于 linux。如果您使用的是Windows,则可能需要使用Perl或Python脚本来完成上述所有操作。

for hfile in $(find /header/dir -type f -iname '*.h'); do
sed -i 's/#include "'$hfile'"/#include "'$hfile'"/gI' file1.cpp
done

我希望我把报价正确:)申请前不要-i

您可以将sed调用包装在另一个循环中,如下所示:

for hfile in $(find /header/dir -type f -iname '*.h'); do
for sfile in $(find /source/dir -type f -iname '*.cpp'); do
sed -i 's/#include "'$hfile'"/#include "'$hfile'"/gI' "$sfile"
done
done

这可能对你有用(GNU sed):

sed 's|.*|s/^#include "&"$/#include "&"/i|' list_of_files | sed -i -f - *.{cpp,h} 

感谢您提供有关小写文件名和 #include 字符串的所有详细信息。 但是,我最初的问题是执行字面替换。

下面是满足我要求的基本命令和 sed 脚本。

ls *.h *.H | sed -e "s/([^rn]*)/s/\(\#include\s\"\)1\"/\11\"/gi/g" >> sedcmd.txt

  1. ls *.h *.H创建文件列表,一次一行
  2. 通过管道将此列表传送到 sed。
  3. 搜索整行,这是一个文件名。将整行放在第 1 组中。s/(^rn]*)/
  4. 将整行(文件名)替换为字符串s/(#includes")<filename>"/1<filename>"/gi

字符串#include<space>"放在组 1 中。gii进行不区分大小写的搜索。g是正常的全局搜索和替换。

给定文件名 ACCESS。H 和取消.h,脚本的输出为

s/(#includes")ACCESS.H"/1ACCESS.H"/gi
s/(#includes")cancel.h"/1cancel.h"/gi

最后,sed 命令文件可以与命令一起使用

sed -i.bak -f sedcmd.txt *.cpp *.h

对于包含斜杠的路径名,我的解决方案不会失败(希望您的标题路径中不包含%符号)。

它也快了几个数量级(几百个文件需要~13秒,而不是等待几分钟)。

#!/bin/bash
shopt -s globstar failglob nocaseglob
# You should pushd to your include path-root.
pushd include/path/root
headers=( **/*.h )
popd
headers+=( *.h )    # My codebase has some extra header files in the project root.
echo ${#headers[*]} headers
# Separate each replacement with ;
regex=""
for header in "${headers[@]}"; do
regex+=';s%#include "'"$header"'"%#include "'"$header"'"%gI'
done
regex="${regex:1}"
find . -type f -iname '*.cpp' -print0 | 
xargs -0 sed -i "$regex"

让 sed 每个文件只运行一次要快得多(有许多以 ; 分隔的正则表达式)。