![有人写过脚本来解析某组宏吗?](https://linux22.com/image/238300/%E6%9C%89%E4%BA%BA%E5%86%99%E8%BF%87%E8%84%9A%E6%9C%AC%E6%9D%A5%E8%A7%A3%E6%9E%90%E6%9F%90%E7%BB%84%E5%AE%8F%E5%90%97%EF%BC%9F.png)
想法是这样的:像大多数人一样,我使用了很多自定义宏,这些宏通常只不过是我经常使用的命令的缩写版本。这对我来说很好,但对于需要阅读的人来说,这会让 latex 变得晦涩难懂。
有人知道解决/扩展特定宏组的方法吗?它可以将一个tex
文件和一个或多个sty
包含宏的文件作为输入,并从文件中删除tex
文件中的所有宏sty
,留下tex
不再需要这些sty
文件的文件。
答案1
以下是我为此使用的非常简单的 perl 函数。apply_tex_macros($macros,$tex) 接受 $macros 和 $tex 中的 TeX 代码,从 $macros 中读取宏定义,并在 $tex 中出现这些宏时对其进行扩展。它不是完全通用的,但对我的应用程序来说已经足够好了。
sub apply_tex_macros {
my $macros = shift;
my $tex = shift;
my $orig = $tex;
$macros =~ s/(?<!\\)\%.*//; # remove comments
my $curly = "(?:(?:{[^{}]*}|[^{}]*)*)"; # match anything, as long as curly braces in it are matched, and not nested
my $curlycurly = "(?:(?:{$curly}|$curly)*)"; # allow one level of nesting
my $curlycurlycurly = "(?:(?:{$curlycurly}|$curlycurly)*)"; # allow two levels of nesting
my $before;
while ($macros =~ /\\newcommand{\\([a-zA-Z\-]+)}\s*(?:\[(\d+)\])\s*(?:\[($curlycurlycurly)\])\s*{($curlycurlycurly)}/g) {
my $command = $1;
if ($tex=~/\\$command/) {print STDERR "Warning in footex, command $command with optional arguments is not supported, in input $tex.\n"}
}
my $depth = 0;
do {
$before = $tex;
while ($macros =~ /\\newcommand{\\([a-zA-Z\-]+)}\s*(?:\[(\d+)\])?\s*{($curlycurlycurly)}/g) {
my ($command,$nargs,$def) = ($1,$2,$3);
if (!$nargs) {
$tex =~ s/\\$command/$def/g;
}
if ($nargs==1) {
while ($tex =~ m/\\($command\{($curlycurlycurly)\})/) {
my ($macro,$arg) = ($1,$2);
my $result = $def;
$result =~ s/#1/$arg/g;
my $foo = quotemeta $macro;
$tex =~ s/\\$foo/$result/g;
}
}
if ($nargs==2) {
while ($tex =~ m/\\($command\{($curlycurlycurly)\}\{($curlycurlycurly)\})/) {
my ($macro,$arg1,$arg2) = ($1,$2,$3);
my $result = $def;
$result =~ s/#1/$arg1/g;
$result =~ s/#2/$arg2/g;
my $foo = quotemeta $macro;
$tex =~ s/\\$foo/$result/g;
}
}
if ($nargs>2 && $tex=~/\\$command/) {print STDERR "Warning in footex, command $command with more than 2 arguments is not supported, in input $orig.\n"}
}
++$depth;
print STDERR "Warning, macro expansion isn't bottoming out, depth=$depth, tex=$tex\n" if $depth>=28;
} while ($tex ne $before && $depth<30);
return $tex;
}
答案2
我已经按照这些思路编写了一些脚本,但我的目标是在 LaTeX 和其他一些标记格式(Markdown 或其变体)之间进行更多转换。我先从一个简单的 perl 脚本开始,该脚本扩展了一些 LaTeX 宏(可以处理基本内容),然后是一个 PHP 程序,将一些 LaTeX 内容转换为 XHTML+MathML,接下来是一个 Perl 脚本,该脚本试图模拟 TeX(catcode 和所有内容,因此基本上教 Perl TeX 的所有细微差别),最后是一个可以与 TeX 本身一起运行的样式文件,它输出一个文本文件(嗯,实际上是一个 PDF,但具有固定宽度的字体并且没有连字符,因此可以pdftotext
完美地将其转换为文本文件),适合输入到下一个标记处理器。
我期望的输出的一个组件是 itexToMML 程序,它将 LaTeX 数学输出的子集转换为 MathML。因此,我必须弄清楚的一件事是如何“转义”某些宏,以便不是处理,同时允许处理其他宏。这正是您所要求的,只不过它通过宏白名单起作用不是要处理的宏比应该处理的宏黑名单要多。
如果以上任何内容对您有用,请随时联系我以获取更多详细信息。