LaTeX 解析器对标签(命令)及其内容执行操作?

LaTeX 解析器对标签(命令)及其内容执行操作?

是否有可用的 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.stymodify-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保存旧的“程序”而不是其“结果”。


编辑:代码已更新

答案3

Sed 和 Awk是你的朋友。它们应该足够强大,可以处理嵌套标签等。(不过我不太确定)

另一种方法是看看特克斯考特看看它如何解析事物,看看是否有帮助......

答案4

我可能会选择 perl,因为它可以使用正则表达式来匹配平衡文本或者使用以下模块文字::平衡

但也许这只是我的想法。

相关内容