用 xstring 替换 chars。Catcode 问题

用 xstring 替换 chars。Catcode 问题

我尝试做这样的事情(最小的例子):

\documentclass[]{article}
\usepackage{mathtools}
\usepackage{xstring}

\newcommand{\foo}[1]{
    \StrSubstitute{#1}{:}{\string&}[\fooo]
    \StrSubstitute{\fooo}{-}{\string\\}[\fooo]
    \tokenize{\fooo}{\fooo}
    \fooo}


\begin{document}


\[\begin{matrix}
    \foo{1:2-2:3}
\end{matrix}\]
\end{document}

但是我它不起作用,由于某种原因这是有效的:

\documentclass[]{article}
\usepackage{mathtools}
\usepackage{xstring}

\begin{document}

\StrSubstitute{1:2-2:3}{:}{\string&}[\fooo]
\StrSubstitute{\fooo}{-}{\string\\}[\fooo]
\tokenize{\fooo}{\fooo}

\[\begin{matrix}
    \fooo
\end{matrix}\]
\end{document}

对此有什么想法吗?我认为这与 catcodes 有关...

也许有人对这种行为也有解释?

答案1

您的代码无法运行的原因是matrix环境(或者更确切地说,底层\halignTeX 基元)&在 xstring 操作它时(更准确地说,在执行\tokenize步骤时)可以看到。TeX 认为这是单元格的末尾,插入单元格末尾的材料,包括内部基元\endtemplate,这会使 xstring 宏阻塞。如果您想看到这种情况,请\tracingall在之前添加\tokenize,并得到令人困惑的输出。

那么……我们如何躲避&TeX 好奇的目光?事实证明,如果 TeX 看到&(或者更确切地说,带有 catcode 4 的标记,对齐制表符)而它认为该标记在括号内,则该&标记将保持原样,而不会转换为单元格的末尾。因此,例如,\def\foo{&}在对齐中出现时不会使 TeX 阻塞:&隐藏。另一方面,\begin{matrix}abc\string &\end{matrix}不会显示&,而是显示$(单元格末尾材料中的第一个字符)。有关更多信息,请参阅Philippe Goutet 的描述\alignsafe@testopt

无论如何,一个解决方案是将所有 xstring 命令放在括号组内,然后\fooo在其后展开:类似于

\begin{matrix}
  {\StrSubstitute{1:2-3:4}{:}{\string&}[\fooo]
  \StrSubstitute{\fooo}{-}{\string\\}[\fooo]
  \tokenize{\fooo}{\fooo}
  \expandafter}\fooo
\end{matrix}

(如果愿意,可以将其包装在命令中)。这样做的缺点是我们基本上是{}1&2\\3&4在为 TeX 排版,而空括号组在某些情况下可能会影响间距。相反,我会使用“假”括号\iffalse{\fi\iffalse}\fi,这会让 TeX 认为这&不是单元格的结尾,但不会插入任何要排版的内容。下面\relax代码中的额外内容是必要的,因为否则 TeX 会在单元格开头完全展开材料,\iffalse{\fi在尚未记录括号数量时展开得太早。

\documentclass{article}
\usepackage{mathtools}
\usepackage{xstring}
\newcommand{\foo}[1]{%
    \relax\iffalse{\fi            % <= here
    \StrSubstitute{#1}{:}{\string&}[\fooo]%
    \StrSubstitute{\fooo}{-}{\string\\}[\fooo]%
    \tokenize{\fooo}{\fooo}%
    \iffalse}\fi                  % <= and there
    \fooo}
\begin{document}
\[\begin{matrix}
    \foo{1:2-2:3}
\end{matrix}\]
\end{document}

\tokenize其他答案指出,如果你用\string&by&\string\\by \\(或\tabularnewline) 替换,并且小心扩展,则不需要此步骤。然后,事实证明,&在括号外从未见过 (仅在\def\...{...&...}括号内),这就是 TeX 不会阻塞的原因。

\tokenizeEDIT2:LaTeX3 具有与(即\tl_gset_rescan:Nnn和朋友)类似的功能,并且它们具有与\tokenize(即用户提供的参数并不总是隐藏在括号后面)相同的“错误”。截至 12 月 18 日(今天),该问题已在 svn 中得到修复。

答案2

尝试以下代码,其中:,被 替换为&

\documentclass[]{article}
\usepackage{mathtools}
\usepackage{xstring}
\newcommand\foo[1]{%
    \saveexpandmode\expandarg
    \StrSubstitute{\noexpand#1}:&[\fooo]%
    \StrSubstitute\fooo,&[\fooo]%
    \StrSubstitute\fooo-{\noexpand\\}[\fooo]%
    \restoreexpandmode\[\begin{matrix}\fooo\end{matrix}\]}
\begin{document}
\foo{1:2-2:3-x,y}
\end{document}

答案3

您可以尝试以下方法:

\documentclass[]{article}
\usepackage{mathtools}
\usepackage{xstring}

\newcommand{\foo}[1]{%
\begingroup
\catcode`\&=12
\noexpandarg
    \StrSubstitute{#1}{-}{\tabularnewline}[\fooo]
\expandarg
    \StrSubstitute{\fooo}{:}{&}[\fooo]
\expandafter\endgroup
    \fooo}


\begin{document}


\[\begin{matrix}
    \foo{1:2-2:3-4444:55555}
\end{matrix}\]
\end{document}

相关内容