【问题标题】:perl how to extract #define'd number from C header fileperl如何从C头文件中提取#define'd数字
【发布时间】:2018-08-24 23:19:39
【问题描述】:

我正在寻找一个 Perl sn-p 来将 C 标头中包含的数字 100 打印到终端。

#ifndef VERSIONS_H
#define VERSIONS_H

#define __SOFTWARE_REVISION__ 100

#endif

我可以提取#define 行,但是数字。

#!perl -w
use warnings;
use strict;
my $line;
my $file = shift @ARGV;
open my $fh, "<", $file or die $!;
while (<$fh>) {
        print if /__SOFTWARE_REVISION__/;
}
close ($fh);

【问题讨论】:

  • 这也会打印出使用宏的每一行。您需要在正则表达式中包含 #define 部分。另外,查找捕获组以及如何匹配数字。
  • 您可以使用gcc 以干净的格式获取定义:gcc -E -dM hdr.h | grep __SOFTWARE_REVISION__。除非你有其他理由使用 Perl 来解决这个问题。
  • 在@rici 发表评论之后,我可能会建议使用gcc 来提取定义。 (然后在 Perl 中选择您需要的那个。我假设这是在 Perl 程序中出现的;我不会为此选择 Perl。)在我的答案中添加了评论。
  • 一种特别令人发指的方法是使用h2xs,因为它的真正目的是将C 头文件转换为Perl 的XS 胶水。但是,不要那样做。 :)

标签: c regex perl c-preprocessor


【解决方案1】:

正则表达式匹配包含该文字短语的任何行,而不仅仅是定义它的位置。您需要更精确地指定线路,并捕获所需的数字。

代码还会继续不必要地循环文件。

还有一些调整

use warnings;
use strict;
use feature qw(say);

my $file = shift @ARGV;
die "Usage: $0 filename\n" if not $file or not -f $file;

open my $fh, '<', $file or die "Can't open $file: $!";

while (<$fh>) {
    if (/^\s*#\s*define\s+__SOFTWARE_REVISION__\s+([0-9]+)/) {
        say "Software revision: $1";
        last;
    }
}
close $fh;

如果版本可以不是整数,则将 [0-9]+ 替换为允许使用句点的模式 [0-9.]+,或者 [0-9.a-z] 如果版本控制中允许使用(小写)字母...或简单地替换为 \S+ .

我建议在手头参考perlre 完成教程perlretut


我假设这种需求出现在 Perl 程序中(而不是 Perl 是为此选择的工具)。

不过,请注意,还有其他更系统的方法可以使用编译器检索此信息(例如,请参阅 ricigcc 的评论)。

虽然在 Perl 脚本中使用 Perl 比使用系统更好,但 这种 情况可能是例外之一:使用外部命令可能比解析源代码更好文件,这是众所周知的危险任务。

【讨论】:

  • # 之后和define 之前可能有空格,所以改成#\s*。从技术上讲,您也可以在 #define 之后使用 cmets,但这不太可能。我宁愿不为行尾指定任何锚点。
  • @giusti 好点,谢谢;没有理由对[0-9]+\S+ 之后的内容进行任何限制。已修复,并添加注释
【解决方案2】:

这是一种使用正则表达式来捕获版本号(如果存在于一行中)的方法。请注意,正则表达式中的括号分隔捕获组,变量$1 用于访问捕获。

#!perl -w
use warnings;
use strict;

my $file = shift @ARGV;
open my $fh, "<", $file or die $!;

while (<$fh>) {
    print "$1\n" if /^#define +__SOFTWARE_REVISION__ +(\d+)$/;
}

close $fh;

输出:

100

正则表达式比你的更具选择性,它匹配一行中__SOFTWARE_REVISION__ 的任何实例。此正则表达式匹配行首的#define,后跟一个或多个空格,然后是__SOFTWARE_REVISION__,后跟一个或多个空格,最后是一个或多个数字捕获组。

【讨论】:

  • 是否需要unix行尾格式?我正在运行 windows perl,并且 ggorlen 和 zdim 示例都没有输出。 gcc 方法可能与 grep 正则表达式一起使用?也没有成功。
  • 结束了:grep "([0-9][0-9][0-9])" versions.h |尾 -c6
  • 我在 Win 10 上使用 Strawberry Perl(这是为 MSWin32-x64-多线程构建的 perl 5,版本 26,subversion 1 (v5.26.1))。加载文件是否正常(即您可以打印)?
猜你喜欢
  • 2017-06-16
  • 2011-01-21
  • 1970-01-01
  • 2011-02-22
  • 1970-01-01
  • 1970-01-01
  • 2010-11-11
  • 2021-08-15
相关资源
最近更新 更多