Perl:正则表达式不抓取代码中的多行 C 风格注释

2024-05-20

我有一个 Perl 程序:

  • 读取用 C 编写的 SRC 文件
  • 使用 SRC 文件中的正则表达式匹配来查找特定格式的数据以用作目标文件名
  • 打开新的目标文件
  • 执行另一个正则表达式匹配以查找包含关键字 abcd 的所有 C 风格注释 /* */。注意:这些注释可以是 1 行或多于 1 行,因此正则表达式会查找第一个 /*,然后查找关键字 abcd,然后在遇到结束符之前查找任意数量的文本和空格 */
  • 将正则表达式匹配写入目标文件
#!/usr/bin/perl
use warnings;
use strict;

my $src = 'D:\\Scripts\\sample.c';
my $fileName;

# open source file for reading
open(SRC_FH,'<',$src) or die $!;

while(my $row = <SRC_FH>){
    if ($row =~ /([0-9]{2}\.[0-9]{2}\.[0-9]{3}\.[a-z,0-9]{2}|[0-9]{2}\.[0-9]{2}\.[0-9]{3}\.[a-z,0-9]{3})/){
        $fileName = $1;
    }
}

my $des = "D:\\Scripts\\" . $fileName . ".txt";

# open destination file for writing
open(DES_FH,'>',$des) or die $!;

print("copying content from $src to $des\n");

seek SRC_FH, 0, 0;

while(my $row = <SRC_FH>){
    if ($row =~ /(\/\*.*abcd.[\s\S]*?\*\/)/){
        print DES_FH "$1\n";
    }
}

# always close the filehandles
close(SRC_FH);

close(DES_FH);
print "File content copied successfully!\n";

我的问题是,我认为由于 perl 代码的执行方式,尽管正则表达式是正确的,但我的目标文件仅写入了 1 行注释。任何超过 1 行的 C 风格注释都不会写入目标文件。我的第二个 if 语句中缺少什么?

我在这里检查了我的第二个 if 语句正则表达式https://regexr.com/ https://regexr.com/它的工作原理是捕获多行 C 风格注释以及也包含关键字 abcd 的单行注释。

所以我尝试了 zdim 下面的第一个建议。这是我使用的:

#!/usr/bin/perl
use warnings;
use strict;

my $src = 'D:\\Scripts\\sample.c';
my $fileName;
my @comments;

# open source file for reading
open(SRC_FH,'<',$src) or die $!;

while(my $row = <SRC_FH>){
    if ($row =~ /([0-9]{2}\.[0-9]{2}\.[0-9]{3}\.[a-z,0-9]{2}|[0-9]{2}\.[0-9]{2}\.[0-9]{3}\.[a-z,0-9]{3})/){
        $fileName = $1;
    }
}

my $des = "D:\\Scripts\\" . $fileName . ".txt";

# open destination file for writing
open(DES_FH,'>',$des) or die $!;

print("copying content from $src to $des\n");

#seek SRC_FH, 0, 0;

my $content = do {
    #read whole file at once
    local $/;
    open (SRC_FH,'<', $src) or die $!;
    <SRC_FH>;
};

#if($content =~ /(\/\*.*abcd.[\s\S]*?\*\/)/sg){
#       my @comments = $content;
#   }

my @comments = $content =~ /(\/\*.*abcd.[\s\S]*?\*\/)/sg;

foreach (@comments){
    print DES_FH "$1\n";
}

#while(my $row = <SRC_FH>){
#   if ($row =~ /(\/\*.*abcd.[\s\S]*?\*\/)/){
#       print DES_FH "$1\n";
#   }
#}

# always close the filehandles
close(SRC_FH);

close(DES_FH);
print "File content copied successfully!\n";

结果是将sample.c 中的所有内容复制到目标文件。完整的 1:1 副本。我希望从 C 文件中提取所有单行和多行注释。

示例1: /* A B C D */ 示例2: /* 一些文本 * 更多评论 abcd 和一些更多评论 */

最终解决方案

#!/usr/bin/perl
use warnings;
use strict;

my $src = 'D:\\Scripts\\sample.c';
my $fileName;

# open source file for reading
open(SRC_FH,'<',$src) or die $!;

while(my $row = <SRC_FH>){
    if ($row =~ /([0-9]{2}\.[0-9]{2}\.[0-9]{3}\.[a-z,0-9]{2}|[0-9]{2}\.[0-9]{2}\.[0-9]{3}\.[a-z,0-9]{3})/){
        $fileName = $1;
    }
}

my $des = "D:\\Scripts\\" . $fileName . ".txt";

# open destination file for writing
open(DES_FH,'>',$des) or die $!;

print("copying content from $src to $des\n");

seek SRC_FH, 0, 0;

my $content = do{local $/; <SRC_FH>};

my @comments = $content =~ /(\/\*.*abcd.[\s\S]*?\*\/)/g;

for(@comments){
    print DES_FH "$_\n";
}

# always close the filehandles
close(SRC_FH);

close(DES_FH);
print "File content copied successfully!\n";

我的第二个 if 语句中缺少什么?

好吧,没什么——只是在多行 C 注释中,它的两行都没有/* and */。因此,当逐行读取文件时,正则表达式无法匹配多行注释。

要捕获此类评论:

  • 将整个文件读入字符串(“slurp”它),然后添加/s正则表达式上的修饰符,以便.也匹配换行符。还使用/g修饰符 so 可以捕获字符串中的所有此类模式。单程

    my $content = do { 
        local $/;  # undef record separator so the whole file is read at once
        open my $src_fh, '<', $src_file or die $!;  # have to re-open
        <$src_fh>;                                  # reads it all
    };  # lexical filehandle gets closed as we leave scope
    
    # NOTE -- there may be difficulties in capturing comments in a C source file
    my @comments = $content =~ /.../sg;  # your regex
    

    或者使用库来获取文件,例如

    use Path::Tiny;
    my $content = path($src_file)->slurp; 
    

Or,

  • 当你看到时设置一个标志/*,获取/打印所有行,直到结束*/,然后取消设置该标志。这是一个基本版本

    my $inside_comment = 0;
    while (<$src_fh>) {
        if (m{(/\*.*)}) {         #/ fix syntax hilite
            $inside_comment = 1;  # opening line for the comment 
            say $des_fh $1; 
        } 
        elsif (m{(.*\*/)}) {      # closing line for the comment
            say $des_fh $1; 
            $inside_comment = 0; 
        } 
        elsif ($inside_comment) { say $des_fh $_}
    }
    

    我测试了所有这些,但请检查并改进。其一,这对于前导空格来说很有趣。

注意:从 C 程序中获取所有注释通常可能相当棘手。


这是单行版的 slurping

my $file_content = do { local (@ARGV, $/) = $file_name; <> }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Perl:正则表达式不抓取代码中的多行 C 风格注释 的相关文章

随机推荐

  • finish() 完成活动但它仍然在后台

    我有一个关于 android studio 中活动的 finish 方法的问题 我有这个简单的代码 public class MainActivity extends AppCompatActivity Override protected
  • 合并两个(或更多)PDF

    背景 我需要为我的销售人员提供每周报告包 该包包含几个 5 10 个水晶报告 Problem 我想允许用户运行所有报告并且只运行单个报告 我想我可以通过创建报告然后执行以下操作来做到这一点 List
  • 如何创建一个语句来打印以特定单词开头的单词? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何在 python 中打印从特定字母开始的单词 而不使用函数 而是使用方法或循环 1 我有一个字符串 想要打印以 m 开头的单词 S
  • 检查缓存后 System.Web.HttpContext.Current 自身为空

    今天我遇到了一个奇怪的问题 这对我来说毫无意义 总结如下 在方法内部 我检查缓存的项目 如下所示 private async Task
  • Graphviz:能够接受更大文件的在线工具[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道有一个很好的在线网站来渲染 graphviz 点文件 该文件将需要更大的文件 例如 200 行
  • 更改 Grafana 端口

    我目前在 Grafana 中有 InfluxDB 提供仪表板 我最终将在服务器上部署这个堆栈 但是 Grafana 的默认端口是 80 我必须更改此端口 但我不知道如何更改 有人可以帮忙吗 Thanks 变化不仅在于 etc grafana
  • TransactionScope 是否需要开启 DTC 服务?

    根据我的阅读 为了在 NET 中使用 TransactionScope 您需要运行 Windows 中的分布式事务协调器服务 我有那个服务关掉 并且我的应用程序似乎运行相同并且回滚事务没有问题 我错过了什么吗 它如何能够发挥作用呢 我正在运
  • 如何使用canvas.toDataURL()将画布保存为图像?

    我目前正在构建一个 HTML5 Web 应用程序 Phonegap 本机应用程序 我似乎不知道如何将画布保存为图像canvas toDataURL 有人可以帮我吗 这是代码 有什么问题吗 我的画布被命名为 canvasSignature J
  • Django Rest Framework:字段名称“likes”对于模型“userPost”配置不正确无效

    在我的 Django Rest Framework api 中 我尝试向我的模型 UserPosts 添加一个属性 该属性返回所述帖子的所有喜欢 尽管我尽了最大努力 但我仍然遇到这个错误 下面是我的帖子模型 class UserPosts
  • 如何将 PhoneGap 与 Visual Studio 结合使用

    我在 Windows 8 VS 2012 上开始使用 PhoneGap 时遇到问题 即 我不知道如何安装模板 我打开从PhoneGap下载的模板项目 但它们与VS2012兼容 我不知道从哪里开始创建我的第一个简单的 CRUD 应用程序 我想
  • 如何使用 jest 模拟第三方库

    我正在开发一个node js应用程序使用nestjs我有一堂课叫LoggerService如下 export class LoggerService private logger Rollbar constructor this logge
  • 具有共享依赖项的多模块项目的 Gradle 配置

    使用 gradle 制作第一个项目 所以我研究了 spring gradle hibernate 项目如何组织 gradle 文件 并开始制作自己的项目 但是 找不到错误 为什么我的配置不起作用 子项目无法解决依赖关系 所以项目树 Root
  • 将数字分解为单个数字的数组

    如果我有整数 123 并且我想将数字分解为数组 1 2 3 最好的方法是什么 我已经搞乱了很多 并且我有以下工作 var number 123 var digits Array String number map Int strtoul S
  • Mysqli 更新抛出 Call to a member function bind_param() 错误[重复]

    这个问题在这里已经有答案了 我有一个 70 80 字段表单 需要插入到表中 因此我首先根据表单中的输入名称在数据库中创建了一个表 而不是手动创建一个巨大的插入语句 这是我使用的代码创建 更改表 function createTable ar
  • Java:正则表达式排除空值

    在问题中here https stackoverflow com questions 51359056 java regexp for a separated group of digits 我得到了正则表达式来匹配 1 到 99 之间的一
  • Ember.js 处理 View 事件后转换到路由

    Setup 我有一个 Ember 应用程序 支持使用 Imgur API 上传图像 我已经有一个工作路线和模板来处理任何 Imgur ID 但我想在上传新图像后转换到此路线 使用返回的 Imgur ID 这是该应用程序的相关部分 http
  • 如何获取 WebElement 的父级[重复]

    这个问题在这里已经有答案了 我试过了 private WebElement getParent final WebElement webElement return webElement findElement By xpath 但我得到
  • 查询参数更改时,路线不会更新

    在我的应用程序中 有多个链接 其中我有一些links与相同的route但与不同的query parameters 比如说 我有这样的链接 deposits withdrawals deposits withdrawals id 1 depo
  • 如何使用自定义 DbFunction 将字符串转换为小数

    我有一个将小数 和其他类型 保存为字符串的表 我想在数据库上下文上编写一个 Linq 查询 该查询将转换为数据库转换而不是本地转换 出于性能原因 This 非工作的example 从概念上讲是我想要实现的目标 using var conte
  • Perl:正则表达式不抓取代码中的多行 C 风格注释

    我有一个 Perl 程序 读取用 C 编写的 SRC 文件 使用 SRC 文件中的正则表达式匹配来查找特定格式的数据以用作目标文件名 打开新的目标文件 执行另一个正则表达式匹配以查找包含关键字 abcd 的所有 C 风格注释 注意 这些注释