![构建 \externaldocument 命令的参数以实现可编程的交叉引用](https://linux22.com/image/406251/%E6%9E%84%E5%BB%BA%20%5Cexternaldocument%20%E5%91%BD%E4%BB%A4%E7%9A%84%E5%8F%82%E6%95%B0%E4%BB%A5%E5%AE%9E%E7%8E%B0%E5%8F%AF%E7%BC%96%E7%A8%8B%E7%9A%84%E4%BA%A4%E5%8F%89%E5%BC%95%E7%94%A8.png)
我的 ver12.tex 和 ver12_SM.tex 文档使用 xr 包相互交叉引用。我该如何对它们进行编程,以便当转到 ver13 时,两个 \externaldocument 命令可以完成它们的工作,而无需手动将当前文件名硬编码到它们中。
以下行会产生编译错误:
\usepackage{xstring}
\usepackage{xr}
\externaldocument[M-]{\StrBefore*{\jobname}{_SM}
谢谢!
答案1
你可以使用一种方式
\externaldocument{\jobname_SM}
在另一个中你可以使用
{
\catcode`\_=12
\catcode`\S=12
\catcode`\M=12
\gdef\stripsm#1_SM{#1}
}
\externaldocument{\expandafter\stripsm\jobname}
答案2
那么这两个文件的名字的模式就是
⟨common part of the two filenames⟩.tex
和
⟨common part of the two filenames⟩_SM.tex
?
宏的问题字符串-package 的一个缺点是它们不可扩展。
这意味着它们不只是提供在 LaTeX 的胃中处理/扩展的标记,并且在扩展后产生字符标记序列。它们还提供不可扩展的标记,用于执行\def
在 LaTeX 的胃中执行的临时任务(等等)。这种不可扩展的非字符标记不能成为文件名的一部分。在胃中,形成文件名的字符标记序列应该已经存在,而不是与其他不可扩展的标记交错,因为文件名的进一步处理也在胃中进行。
因此,使用宏字符串-package 您需要使用它们的可选参数来定义扩展为操作结果的宏:
\documentclass{article}
\usepackage{xr}
\usepackage{xstring}
%======================================================================%
% This will check whether the token-sequence that forms the expansion %
% of \jobname ends with "_SM". %
% If so, \JobNameWithOrWithoutSMPhrase will be defined to expand to %
% the result of removing the last occurrence of "_SM" from the %
% expansion of \jobname. %
% If not so, \JobNameWithOrWithoutSMPhrase will be defined to expand %
% to the result of appending the phrase "_SM" to the expansion of %
% \jobname. %
\newcommand\JobNameWithOrWithoutSMPhrase{}%
\begingroup
\makeatletter
\def\SMPhrase{_SM}%
\@onelevel@sanitize\SMPhrase
\IfEndWith{\jobname}{\SMPhrase}{%
\StrCount{\jobname}{\SMPhrase}[\JobNameWithOrWithoutSMPhrase]%
\StrBefore[\JobNameWithOrWithoutSMPhrase]{\jobname}{\SMPhrase}[\JobNameWithOrWithoutSMPhrase]%
}{%
\expandafter\expandafter
\expandafter \def
\expandafter\expandafter
\expandafter \JobNameWithOrWithoutSMPhrase
\expandafter\expandafter
\expandafter {%
\expandafter\jobname
\SMPhrase}%
}%
\global\let\JobNameWithOrWithoutSMPhrase=\JobNameWithOrWithoutSMPhrase
\endgroup
%======================================================================%
\message{^^J\string\jobname\space expands to:^^J\jobname}
\message{^^JPress return to proceed.}
\immediate\read-1 to\MyScratchmacro
\message{^^JMeaning of \string\JobNameWithOrWithoutSMPhrase\space is:^^J\meaning\JobNameWithOrWithoutSMPhrase}
\message{^^JPress return to proceed.}
\immediate\read-1 to\MyScratchmacro
\externaldocument[M-]{\JobNameWithOrWithoutSMPhrase}
\begin{document}
Bla Bla
\end{document}
而不是使用字符串您可以使用分隔参数让 LaTeX 检测形成扩展的标记序列是否\jobname
以该序列结尾_SM
,如果是,则定义控制字标记以扩展为删除短语\JobNameWithOrWithoutSMPhrase
的扩展,如果不是,则定义控制字标记以扩展为附加短语的扩展。\jobname
_SM
\JobNameWithOrWithoutSMPhrase
\jobname
_SM
您可能面临的一个问题是,在对 .tex-input-file 中的\jobname
短语进行标记时,通常会产生类别代码为 8(下标)的下划线 ( ),后面跟着类别代码为 11(字母)的和。因此,对于从 .tex-input 标记的字符标记序列,您可能需要申请将所有这些字符转换为类别代码为 12(其他)的挂件。(至于空格的例外:将空格字符标记转换为类别代码为 10(空格)的空格字符标记。)_SM
_
S
M
\@onelevel@sanitize
\@onelevel@sanitize
\documentclass{article}
\usepackage{xr}
%======================================================================%
% This will check whether the token-sequence that forms the expansion %
% of \jobname ends with "_SM". %
% If so, \JobNameWithOrWithoutSMPhrase will be defined to expand to %
% the result of removing the last occurrence of "_SM" from the %
% expansion of \jobname. %
% If not so, \JobNameWithOrWithoutSMPhrase will be defined to expand %
% to the result of appending the phrase "_SM" to the expansion of %
% \jobname. %
% For detecting the end, advantage is taken of the fact that the %
% expansion of \jobname cannot contain any control-sequence-token %
% and therefore cannot contain the control-word-token \relax. %
% The empty-test via \if\relax<stuff>\relax..\else..\fi also takes %
% advantage of this fact and of the fact that \if triggers expansion %
% until finding two non-expandable tokens whose character-codes can be %
% compared, while for control-word-tokens like \relax a character-code %
% outside the range of character-codes possible for character-tokens %
% is assumed. %
\newcommand\JobNameWithOrWithoutSMPhrase{}%
\begingroup
\makeatletter
\def\SMPhrase{_SM}%
\@onelevel@sanitize\SMPhrase
\expandafter\def\expandafter\GobbleToSMPhraseNRelax
\expandafter#\expandafter1\SMPhrase\relax{}%
\expandafter\def\expandafter\RemoveSMPhraseNRelax
\expandafter#\expandafter1\SMPhrase\relax{#1}%
\edef\JobNameWithOrWithoutSMPhrase{%
\if\relax\expandafter\expandafter
\expandafter \GobbleToSMPhraseNRelax
\expandafter\jobname
\expandafter\relax
\SMPhrase\relax\relax
\jobname\SMPhrase
\else
\expandafter\RemoveSMPhraseNRelax\jobname\relax
\fi
}%
\global\let\JobNameWithOrWithoutSMPhrase=\JobNameWithOrWithoutSMPhrase
\endgroup
%======================================================================%
\message{^^J\string\jobname\space expands to:^^J\jobname}
\message{^^JPress return to proceed.}
\immediate\read-1 to\MyScratchmacro
\message{^^JMeaning of \string\JobNameWithOrWithoutSMPhrase\space is:^^J\meaning\JobNameWithOrWithoutSMPhrase}
\message{^^JPress return to proceed.}
\immediate\read-1 to\MyScratchmacro
\externaldocument[M-]{\JobNameWithOrWithoutSMPhrase}
\begin{document}
Bla Bla
\end{document}
顺便一提:
test.tex
您可以通过在 shell 上保存并运行 latex 来测试上述示例。
如果你运行不带 -option 的 latex -jobname
,即,latex test.tex
,\jobname
则会扩展为test
(类别代码 12(other) 的所有字符) 并\meaning\test
显示:macro:->test_SM
如果您使用 -option 运行 latex-jobname
以提供尾随的_SM
,即,latex -jobname=test_SM test.tex
那么\jobname
将扩展为test_SM
(类别代码 12(其他) 的所有字符) 并\meaning\test
显示:macro:->test