You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Perl高效实现DS代码系统中分类与代码名称的合并?

你的Perl脚本方案评估与正则问题解析

一、原始逐行脚本的高效性

你的第一个单行脚本其实是非常高效且适合这个需求的方案,原因如下:

  • 流式处理,内存友好:它用-n逐行读取文件,不需要把整个文件加载到内存中,哪怕处理几GB大的.mch文件也不会有内存压力。
  • 逻辑简单直接:通过跟踪当前分类$cat,遇到CODE行就输出分类+代码名称,没有复杂的正则回溯,执行速度快。
  • 易维护:代码逻辑清晰,后续如果要修改格式或者增加处理规则,很容易调整。

完全没必要替换成更复杂的方案——这个脚本已经完美解决了你的需求,而且是最优解之一。

二、正则替换脚本的问题分析

你尝试的-0777全文件正则替换脚本,为什么只捕获每个分类下的最后一个代码名称?

核心原因是正则捕获组在重复匹配时会被覆盖:
你的正则里的(?:CODE \d (.*)(?s).+?(?-s))+是一个重复的非捕获组,其中的(.*)捕获组在每次匹配CODE行时都会更新它的值,当整个组匹配完成后,捕获组里只保留最后一次匹配到的内容,所以每个分类下只会输出最后一个CODE的名称。

三、如果一定要用全文件匹配的改进方案

如果你坚持想用一次性读取整个文件的方式处理,可以用循环匹配的方式,避免捕获组被覆盖的问题。比如下面的脚本:

perl -0777 -ne '
    my $current_cat;
    # 遍历所有CAT和对应的CODE行
    while (/
        (?:^|\G)
        (?:CAT (\V+)\s*(?s).*?)?  # 匹配分类,更新当前分类
        CODE \d (\V+)             # 匹配代码名称
        (?s).*?                   # 跳过代码内容
    /gx) {
        $current_cat = $1 if defined $1;  # 遇到新分类就更新
        print "$current_cat, $2\n" if $current_cat;
    }
' 'Mario Kart DS (USA).mch'

这个脚本用\G锚点来连续匹配,确保从上次匹配结束的位置继续查找,同时每次遇到CAT行就更新当前分类,遇到CODE行就输出对应内容,这样就能正确捕获每个分类下的所有代码名称。

不过还是要强调:原始的逐行处理脚本在性能和简洁性上都更优,除非有特殊需求,否则没必要替换。

内容的提问来源于stack exchange,提问作者noabody

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 17:25:25