为什么 Text::Balanced::extract_bracketed 不提取 LaTeX 标签内的文本?

1 perl parsing latex

我正在尝试使用extract_bracketedText::Balanced 解析平衡文本(实际上是用 LaTeX 编写的文本)。但是,我没有得到与以下代码的正确匹配:

use Text::Balanced qw(extract_bracketed);

my $data = 'xxx \footnote{...} yyy';
(my $ext, my $rem, my $pre) = extract_bracketed($data, '{}', '\footnote');
print "\$ext = $ext\n";
print "\$rem = $rem\n";
print "\$pre = $pre\n";
Run Code Online (Sandbox Code Playgroud)

这打印:

$ext =                                                                                                                  
$rem = xxx \footnote{...} yyy                                                                                           
$pre =
Run Code Online (Sandbox Code Playgroud)

根据文档,这个输出意味着发生了故障,但我不明白为什么。

我真正想要提取的是...,即命令的内容\footnote

为什么会发生这种情况以及如何解决它?

Thi*_*Not 5

Text::Balanced 设置$@失败,以便您可以获得有关原因的详细信息

use strict;
use warnings 'all';
use 5.010;

use Text::Balanced qw(extract_bracketed);

my $text = 'xxx \footnote{...} yyy';
my ($substring, $remainder, $prefix) = extract_bracketed($text, '{}', '\footnote');

warn $@ if $@;
Run Code Online (Sandbox Code Playgroud)

输出:

use strict;
use warnings 'all';
use 5.010;

use Text::Balanced qw(extract_bracketed);

my $text = 'xxx \footnote{...} yyy';
my ($substring, $remainder, $prefix) = extract_bracketed($text, '{}', '\footnote');

warn $@ if $@;
Run Code Online (Sandbox Code Playgroud)

前缀不匹配,因为:

  • 它必须从字符串的开头一直匹配到分隔符的第一次出现

  • \f匹配换页符,而不是后跟字母 f 的反斜杠

以下前缀匹配第一个大括号之前的所有内容:

use strict;
use warnings 'all';
use 5.010;

use Text::Balanced qw(extract_bracketed);

my $text = 'xxx \footnote{...} yyy';

my ($substring, $remainder, $prefix) = extract_bracketed($text, '{}', '[^{}]*');
say "<$_>" for $prefix, $substring, $remainder;
Run Code Online (Sandbox Code Playgroud)

输出:

Did not find prefix: /\footnote/, detected at offset 0 at balanced line 12.
Run Code Online (Sandbox Code Playgroud)

要实际从文本中删除extract_tagged嵌套脚注标记并保留其内容,您需要使用:

use strict;
use warnings 'all';
use 5.010;

use Text::Balanced qw(extract_tagged);

my $text = '\footnote{abc \footnote{...} def \emph{!!!} ghi}';

my @pieces = extract_tagged(
    $text, 
    '\\\footnote{', 
    '}', 
    '(?s).*\\\footnote{.*(?=\\\footnote{)'
);

my ($remainder, $prefix, $contents) = @pieces[1, 2, 4];

say $prefix . $contents . $remainder;
Run Code Online (Sandbox Code Playgroud)

输出:

use strict;
use warnings 'all';
use 5.010;

use Text::Balanced qw(extract_bracketed);

my $text = 'xxx \footnote{...} yyy';

my ($substring, $remainder, $prefix) = extract_bracketed($text, '{}', '[^{}]*');
say "<$_>" for $prefix, $substring, $remainder;
Run Code Online (Sandbox Code Playgroud)

请注意,此方法适用于您提供的简单输入,但不能用作通用 LaTeX 解析器。CPAN 上有几个 LaTeX 解析器,但LaTeX::TOM看起来相当有限,并且LaTeX::Parser自 2000 年以来就没有更新过。

如果您需要进行更复杂的解析,您可能需要编写自己的解析器。