查找以 #define 开头并以 \ 结尾的字符串

查找以 #define 开头并以 \ 结尾的字符串

我正在尝试对 C 代码中的宏定义进行优化。同样,我需要提取 C 文件中存在的所有宏,并且需要查找此特定宏定义出现的次数。

我的宏定义的格式是这样的

#定义 MACRO_NAME DEFN_LINE1\
DEFN_LINE2\
DEFN_LINE3

所以我想我的逻辑是

  1. 使用正则表达式查找以“#define”开头并以“\”结尾的行列表,将上述输出重定向到 MacroLineExtract.txt 文件
  2. 从 MacroLineExtract.txt ==> MACRO_NAME DEFN_LINE1\ 中删除所有“#define”
  3. 删除空格 ===> MACRO_NAME 之后的尾随字符串
  4. 将以上输出保存到文件 Macros.txt 中,该文件现在仅保存我的代码中存在的 MACROS 列表
  5. 编写一个 bash 脚本,从 Macros.txt 中取出一行又一行,并查找 MACRO_NAME 在我的代码中出现了多少次。

你能帮我写一个正则表达式/awk来查找我的c文件中以“#define”开头并以“\”结尾的所有宏吗?如果您有更好的逻辑,请提出相同的建议。

答案1

使用旺盛的ctags

$ ectags --c-kinds=d *.[ch]

ectags是“标签文件”的增强版本ctagsetags用于创建“标签文件”,Vi/Vim 或 Emacs 等编辑器可以使用该文件来轻松导航源代码。它了解 C 语法规则,因此能够为您解析 C 代码(这样您就不必担心正则表达式)。

我们--c-kinds=d告诉我们ectags只关心#defineC 代码中的行。

现在,您在当前目录中拥有一个名为的文件,tags其中包含以下内容:

DEVELOPER       bayes.h 225;"   d
DIFFERENT       bayes.h 227;"   d
DIR_MIN bayes.h 338;"   d
DNA     bayes.h 242;"   d
DOLLAR  bayes.h 309;"   d
DOLLO   bayes.h 276;"   d
DOWN    bayes.h 215;"   d

也就是说,每一行(除了少数标题行)都标识宏的名称、找到该宏的源文件以及行号。如果在多个文件中定义了宏,则每次出现时都会列出一次。最后一个d是标签类型指示器(这些都是#defines)。

如果您只想计算每个宏被定义的次数:

$ cut -f 1 tags | uniq -c

答案2

awk可以进行解析计算在单个操作中,假设您可以传递所有所需的文件名而不超过 ARG_MAX:

awk '$1=="#define"&&/\\$/ {n[$2]++} END {for(i in n) print n[i],i}' *.[ch]

# this includes #define's that are indented with whitespace,
# which the C language allows. If you really want only #defines 
# that start exactly in column 1, use /^#define /&&/\\$/ 

# if you want the columns to line up change the print to something like
#   printf "%6d %s\n",x[i],i

答案3

如果您的文件中存在这样的行:

#定义 MACRO_NAME DEFN_LINE1\

那么这将获得 MACRO_NAME 的唯一值:

cat yourCfile | grep '#define' | awk '{print $2}' | sort -u > macro_names

grep 正在获取包含“#define”的行

awk 将一行中的每个字符串视为一个新字段,使用空格/空格作为默认字段分隔符。所以这里我们只是使用 awk 打印“#define MACRO_NAME DEFN_LINE1\”中的第二个字段,即“MACRO_NAME”。

sort -u > Macro_names 只是删除所有重复项并将所有内容输出到文件中。

并循环遍历宏名称列表并查找包含该宏名称的行数:

for macro in $(cat macro_names); do
count=$(cat yourCfile | grep $macro | wc -l);
echo $macro appears $count times
done

带有“-l”标志的“wc”命令打印从标准输入接收的行数。

答案4

sed '/#define/,\
        /^\(.*[^\]\)*$/N
        /\n\\/P;D'

相关内容