是否有可用的 LaTeX 解析器,可以从 (*nix) 命令行运行,并允许对 LaTeX 标签/命令及其内容进行操作?
例如,我想做的是:
- 通过脚本提取某些文本块,例如
\question{}
内的所有标签\begin{document} ... \end{document}
, 或重命名某些标签([嗯,这是不好的例子,因为很容易做到],\newtext{blabla}
例如\oldtext{blabla}
)- 或删除特定标签及其内容,例如
\oldtext{}
- 或者仅删除标签但保留内容。
不使用 LaTeX 编辑器或类似实用程序的查找和替换的主要原因grep
是嵌套标签和新行上的右括号存在问题。
答案1
由于 OP 提出的问题很笼统,因此我试图找到一个尽可能通用的解决方案。
编辑:我正在完全重写这篇文章,因为我用完全不同的方法编写了另一段代码,并且这个新代码最终应该更加灵活(一旦我理解它)。
将某些命令的参数写入文件比写入外部文本要容易得多。通常必须在以下两者之间做出选择:
读取文件,并以某种方式扩展我们希望忽略的宏:换句话说,在 TeX 的嘴里工作。主要的缺点是,我们(基本上)不允许在扩展过程中使用计数器和定义宏,
让 TeX 排版,并在进行过程中存储相关部分:这需要我们要提取的文本作为某些宏的参数
如果我们想要在中间做一些事情,比如保留所有文本不变直到\begin{document}
,同时对中间的部分内容做一些巧妙的事情(例如,还执行s \newcommand
,或加载一些包),那么我们就会遇到麻烦:我们可能想要做一些不可扩展的事情,同时仍然希望将完整的文本(即不仅仅是命令的参数)写入我们的输出。
因此,我的(第二个)解决方案本质上是使所有字符处于活动状态,并让它们扩展为“写入<char>
文件”或只是“ <char>
”,具体取决于我们当前是扩展还是排版。一种思考方式是,我们正在(模糊地)模拟 TeX 到 dvi 的排版过程,但不是输出到 dvi,而是输出到文本文件。
要使用它,你可以下载和modify.sty
modify-2.tex
和解析如果没有的话,请将infile.tex
和替换outfile.tex
为相关文件,并运行以下最小示例。
\documentclass{minimal}
\input{modify-2.tex}
\begin{document}
\ExplSyntaxOn
\ModifyInput{infile.tex}
\tl_set:Nn \g_modify_actions_tl {
\Modify_Extract:Nn \frac {2} %*
\Modify_Extract:Nn \footnote {1} %*
\Modify_DIY:Nnnnn \emph {1} { \stepcounter{mycounter} }{ %*
\string\emph{\arabic{mycounter}. #1} }{}
}
\ModifyDoWhatever{outfile.tex}
\end{document}
目前,唯一的用户命令是\Modify_Extract:Nn
和\Modify_DIY:Nnnnn
。
\Modify_Extract:Nn \macro {k}
定义\macro
为带有参数的宏k
,并要求将其从文件中提取。\Modify_DIY:Nnnnn \macro {k} {<token list 1>} {<token list 2>} {<token list 3>}
定义\macro
为接受k
参数。当调用它时,宏将执行<token list 1>
,然后“排版”<token list 2>
(必须可扩展)到文件,最后执行<token list 3>
(不确定这是否有用)。例如,\emph
现在将编号(好吧,这很愚蠢,但想想知道我们正在查看的强调文本之前的最后一个脚注的文本)。
对于你的具体问题,我会这样做
\documentclass{minimal}
\input{modify-2.tex}
\begin{document}
\ExplSyntaxOn
\ModifyInput{infile.tex}
\tl_set:Nn \g_modify_actions_tl {
\Modify_Extract:Nn \question {1}
}
\ModifyDoWhatever{outfile.tex}
\end{document}
或者使用一些更花哨的东西\Modify_DIY:Nnnnn
。
事实上,我撒了点小谎:我不会过多地摆弄 catcode:相反,我会用代表每个字符的控制序列替换每个字符。这迫使我\newcommand
以正确的方式实现带有分隔参数的变体。另一个技术问题是空格的处理。
另外,我还没有实现可选参数。而且嵌套目前失败了。我相信这个问题可以通过在扩展或不扩展方面更严谨一些来修复。
答案2
我会重新定义命令/环境来执行您想要的操作,然后调用旧定义。例如,假设您想要\question{}
某个文件中的所有内容(相同的文件名和扩展名“loq”)。
\AtBeginDocument{
\newwrite\myOutputStream
\immediate\openout\myOutputStream=\jobname.loq
}
\AtEndDocument{
\immediate\closeout\myOutputStream
}
\let\oldQuestion\question
\renewcommand\question[1]{\immediate\write\myOutputStream{#1}\noexpand\oldQuestion{#1}} %edited here
上面的代码尚未经过测试,但它应该能让您了解如何继续,至少可以重新定义命令。请注意使用 来let
保存旧的“程序”而不是其“结果”。
编辑:代码已更新