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

如何用Perl对LaTeX文件中{}内的带格式参考编号排序?

Perl 实现LaTeX文件中\refnumbers{}内编号的字母数字排序

需求描述

现有一个包含约10000条记录的LaTeX文件,每条记录由首词和逗号分隔的参考编号组成,部分编号带有\textbf{}、\page{}等LaTeX格式代码。需要对每条记录中\refnumbers{}大括号内的编号进行字母数字排序。

输入示例

ʾallik \refnumbers{9, 4306, 12, 9917, \textbf{28}, 8, 17, 13, 462, 3}
ʾalmin \refnumbers{9, 4306, 12, \textbf{26}, 008, \page{17}, 13, 462, 3}
ʾaran \refnumbers{282, \textbf{300-2}, 391, 829, 1021, 18, 361}

期望输出

ʾallik \refnumbers{3, 8, 9, 12, 13, \textbf{28}, 462, 4306, 9917}
ʾalmin \refnumbers{3, 008, 9, 12, 13, \textbf{26}, 462, 4306, \page{17}}
ʾaran \refnumbers{18, 282, \textbf{300-2}, 361, 391, 829, 1021}

解决方案

1. Perl 命令行版本

直接通过一行命令处理文件,适合快速执行:

perl -pe 's/\\refnumbers\{(.*?)\}/do { my @nums = split /,\s*/, $1; @nums = sort { my $a_val = $a =~ /(\d+(?:-\d+)?)/ ? $1 : $a; my $b_val = $b =~ /(\d+(?:-\d+)?)/ ? $1 : $b; $a_val <=> $b_val } @nums; "\\refnumbers{" . join(", ", @nums) . "}" }/ge' input.tex > output.tex

逻辑说明:

  • -pe:逐行读取输入文件,处理后输出结果
  • 正则匹配\refnumbers{...}结构,提取大括号内的编号字符串
  • 将编号按, 分割为数组,排序时提取每个编号的核心数字(含连字符格式如300-2),用数字比较规则排序
  • 保留原LaTeX格式代码,仅调整编号顺序,最后重新拼接为\refnumbers{...}格式

2. Perl 脚本版本

如果需要更易维护、可扩展的方案,可使用脚本:

创建sort_refnumbers.pl文件:

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

while (my $line = <>) {
    $line =~ s/\\refnumbers\{(.*?)\}/process_refs($1)/ge;
    print $line;
}

sub process_refs {
    my ($refs_str) = @_;
    my @refs = split /,\s*/, $refs_str;
    
    # 按编号核心数字排序,保留原格式
    @refs = sort {
        my $a_num = $a =~ /(\d+(?:-\d+)?)/ ? $1 : $a;
        my $b_num = $b =~ /(\d+(?:-\d+)?)/ ? $1 : $b;
        $a_num <=> $b_num;
    } @refs;
    
    return "\\refnumbers{" . join(", ", @refs) . "}";
}

使用方式:

chmod +x sort_refnumbers.pl
./sort_refnumbers.pl input.tex > output.tex

优势:代码结构清晰,后续若需调整排序规则(如支持更多LaTeX格式),只需修改process_refs函数即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:32:01